From b52e52601711da730aa7e04f461ee7a6eda04824 Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Sat, 3 Apr 2021 17:33:42 +0200 Subject: [PATCH 01/21] Fix: FallbackParagraphLayouter wasn't reverse-mapping glyphs to character indexes right --- src/gfx_layout_fallback.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/gfx_layout_fallback.cpp b/src/gfx_layout_fallback.cpp index f16c8551ef..8656c4ae7d 100644 --- a/src/gfx_layout_fallback.cpp +++ b/src/gfx_layout_fallback.cpp @@ -46,7 +46,7 @@ public: int glyph_count; ///< The number of glyphs. public: - FallbackVisualRun(Font *font, const WChar *chars, int glyph_count, int x); + FallbackVisualRun(Font *font, const WChar *chars, int glyph_count, int char_offset, int x); FallbackVisualRun(FallbackVisualRun &&other) noexcept; ~FallbackVisualRun() override; const Font *GetFont() const override; @@ -104,12 +104,13 @@ public: /** * Create the visual run. - * @param font The font to use for this run. - * @param chars The characters to use for this run. - * @param char_count The number of characters in this run. - * @param x The initial x position for this run. + * @param font The font to use for this run. + * @param chars The characters to use for this run. + * @param char_count The number of characters in this run. + * @param char_offset This run's offset from the start of the layout input string. + * @param x The initial x position for this run. */ -FallbackParagraphLayout::FallbackVisualRun::FallbackVisualRun(Font *font, const WChar *chars, int char_count, int x) : +FallbackParagraphLayout::FallbackVisualRun::FallbackVisualRun(Font *font, const WChar *chars, int char_count, int char_offset, int x) : font(font), glyph_count(char_count) { const bool isbuiltin = font->fc->IsBuiltInFont(); @@ -131,7 +132,7 @@ FallbackParagraphLayout::FallbackVisualRun::FallbackVisualRun(Font *font, const this->positions[2 * i + 1] = 0; // No ascender adjustment. } this->positions[2 * i + 2] = this->positions[2 * i] + font->fc->GetGlyphWidth(this->glyphs[i]); - this->glyph_to_char[i] = i; + this->glyph_to_char[i] = char_offset + i; } } @@ -295,7 +296,7 @@ std::unique_ptr FallbackParagraphLayout::NextLine if (*this->buffer == '\0') { /* Only a newline. */ this->buffer = nullptr; - l->emplace_back(this->runs.begin()->second, this->buffer, 0, 0); + l->emplace_back(this->runs.begin()->second, this->buffer, 0, 0, 0); return l; } @@ -324,7 +325,7 @@ std::unique_ptr FallbackParagraphLayout::NextLine if (this->buffer == next_run) { int w = l->GetWidth(); - l->emplace_back(iter->second, begin, this->buffer - begin, w); + l->emplace_back(iter->second, begin, this->buffer - begin, begin - this->buffer_begin, w); ++iter; assert(iter != this->runs.end()); @@ -369,7 +370,7 @@ std::unique_ptr FallbackParagraphLayout::NextLine if (l->size() == 0 || last_char - begin > 0) { int w = l->GetWidth(); - l->emplace_back(iter->second, begin, last_char - begin, w); + l->emplace_back(iter->second, begin, last_char - begin, begin - this->buffer_begin, w); } return l; } From 103d88ee334a3637c490d9f3c823908e8336b98e Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Sat, 3 Apr 2021 19:48:34 +0200 Subject: [PATCH 02/21] Fix: Layouter not taking stripped formatting codes into account when mapping visual coordinates to/from original string --- src/gfx_layout.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/gfx_layout.cpp b/src/gfx_layout.cpp index 4ed2204363..a17ef42f1c 100644 --- a/src/gfx_layout.cpp +++ b/src/gfx_layout.cpp @@ -206,6 +206,19 @@ Dimension Layouter::GetBounds() return d; } +/** + * Test whether a character is a non-printable formatting code + */ +static bool IsConsumedFormattingCode(WChar ch) +{ + if (ch >= SCC_BLUE && ch <= SCC_BLACK) return true; + if (ch == SCC_PUSH_COLOUR) return true; + if (ch == SCC_POP_COLOUR) return true; + if (ch >= SCC_FIRST_FONT && ch <= SCC_LAST_FONT) return true; + // All other characters defined in Unicode standard are assumed to be non-consumed. + return false; +} + /** * Get the position of a character in the layout. * @param ch Character to get the position of. Must be an iterator of the string passed to the constructor. @@ -228,7 +241,7 @@ Point Layouter::GetCharPosition(std::string_view::const_iterator ch) const auto str = this->string.begin(); while (str < ch) { WChar c = Utf8Consume(str); - index += line->GetInternalCharLength(c); + if (!IsConsumedFormattingCode(c)) index += line->GetInternalCharLength(c); } /* We couldn't find the code point index. */ @@ -282,7 +295,7 @@ ptrdiff_t Layouter::GetCharAtPosition(int x) const if (cur_idx == index) return str - this->string.begin(); WChar c = Utf8Consume(str); - cur_idx += line->GetInternalCharLength(c); + if (!IsConsumedFormattingCode(c)) cur_idx += line->GetInternalCharLength(c); } } } From ee34fae09a6170d38ce3f7ce35bfc7ecccb4c2bf Mon Sep 17 00:00:00 2001 From: translators Date: Mon, 26 Jun 2023 18:42:58 +0000 Subject: [PATCH 03/21] Update: Translations from eints korean: 3 changes by telk5093 danish: 3 changes by bscargo --- src/lang/danish.txt | 5 +++-- src/lang/korean.txt | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/lang/danish.txt b/src/lang/danish.txt index 0d588153fa..525fed90c3 100644 --- a/src/lang/danish.txt +++ b/src/lang/danish.txt @@ -951,6 +951,7 @@ STR_GAME_OPTIONS_VOLUME_100 :100% STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME :{BLACK}Valutaenhed STR_GAME_OPTIONS_CURRENCY_UNITS_DROPDOWN_TOOLTIP :{BLACK}Valg af valutaenhed +STR_GAME_OPTIONS_CURRENCY_CODE :{STRING} ({STRING}) ###length 42 STR_GAME_OPTIONS_CURRENCY_GBP :Britiske Pund @@ -2835,8 +2836,8 @@ STR_AIRPORT_HELISTATION :Helikopterplads STR_AIRPORT_CLASS_SMALL :Små lufthavne STR_AIRPORT_CLASS_LARGE :Store lufthavne -STR_AIRPORT_CLASS_HUB :Central lufthavn -STR_AIRPORT_CLASS_HELIPORTS :Helikopterlufthavn +STR_AIRPORT_CLASS_HUB :Central lufthavne +STR_AIRPORT_CLASS_HELIPORTS :Helikopter lufthavne STR_STATION_BUILD_NOISE :{BLACK}Genereret støj: {GOLD}{COMMA} diff --git a/src/lang/korean.txt b/src/lang/korean.txt index ab8c984a80..bf24a4b662 100644 --- a/src/lang/korean.txt +++ b/src/lang/korean.txt @@ -952,6 +952,7 @@ STR_GAME_OPTIONS_VOLUME_100 :100% STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME :{BLACK}화폐 단위 STR_GAME_OPTIONS_CURRENCY_UNITS_DROPDOWN_TOOLTIP :{BLACK}화폐 단위 선택 +STR_GAME_OPTIONS_CURRENCY_CODE :{STRING} ({STRING}) ###length 42 STR_GAME_OPTIONS_CURRENCY_GBP :영국 파운드 @@ -4574,6 +4575,8 @@ STR_TIMETABLE_EXPECTED :{BLACK}예정 STR_TIMETABLE_SCHEDULED :{BLACK}예정 소요시간 기준 STR_TIMETABLE_EXPECTED_TOOLTIP :{BLACK}시간표 검사 기준을 도착 예정일과 도착 예정 시간 기준 중에서 선택합니다 +STR_TIMETABLE_ARRIVAL :도착: {COLOUR}{DATE_TINY} +STR_TIMETABLE_DEPARTURE :착: {COLOUR}{DATE_TINY} # Date window (for timetable) From e7937efb0199e768910e2d792ff0094c5c93250b Mon Sep 17 00:00:00 2001 From: Rubidium Date: Thu, 22 Jun 2023 17:05:32 +0200 Subject: [PATCH 04/21] Codechange: add clearer named function to get the next (string) parameter --- src/strings.cpp | 16 +++++++++------- src/strings_internal.h | 22 ++++++++++++++++++++-- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/strings.cpp b/src/strings.cpp index e14056758a..b4ce13926e 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -72,26 +72,28 @@ void StringParameters::PrepareForNextRun() /** - * Read an int64 from the argument array. The offset is increased - * so the next time GetInt64 is called the next value is read. + * Get the next parameter from our parameters. + * This updates the offset, so the next time this is called the next parameter + * will be read. + * @return The pointer to the next parameter. */ -int64 StringParameters::GetInt64() +StringParameter *StringParameters::GetNextParameterPointer() { assert(this->next_type == 0 || (SCC_CONTROL_START <= this->next_type && this->next_type <= SCC_CONTROL_END)); if (this->offset >= this->parameters.size()) { Debug(misc, 0, "Trying to read invalid string parameter"); - return 0; + return nullptr; } auto ¶m = this->parameters[this->offset++]; if (param.type != 0 && param.type != this->next_type) { Debug(misc, 0, "Trying to read string parameter with wrong type"); this->next_type = 0; - return 0; + return nullptr; } - param.type = next_type; + param.type = this->next_type; this->next_type = 0; - return param.data; + return ¶m; } diff --git a/src/strings_internal.h b/src/strings_internal.h index 33306aa1e0..c79551fde8 100644 --- a/src/strings_internal.h +++ b/src/strings_internal.h @@ -32,6 +32,8 @@ protected: parameters(parameters) {} + StringParameter *GetNextParameterPointer(); + public: /** * Create a new StringParameters instance that can reference part of the data of @@ -77,12 +79,28 @@ public: this->offset = offset; } - int64 GetInt64(); + /** + * Get the next parameter from our parameters. + * This updates the offset, so the next time this is called the next parameter + * will be read. + * @return The next parameter's value. + */ + template + T GetNextParameter() + { + auto ptr = GetNextParameterPointer(); + return static_cast(ptr == nullptr ? 0 : ptr->data); + } + + int64 GetInt64() + { + return GetNextParameter(); + } /** Read an int32 from the argument array. @see GetInt64. */ int32 GetInt32() { - return (int32)this->GetInt64(); + return GetNextParameter(); } /** From 75a22a1c83cf2f9bd884c194a6e47071820a56ff Mon Sep 17 00:00:00 2001 From: Rubidium Date: Thu, 22 Jun 2023 17:16:28 +0200 Subject: [PATCH 05/21] Codechange: move from GetIntXY to GetNextParameter --- src/strings.cpp | 118 ++++++++++++++++++++++++------------------------ 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/src/strings.cpp b/src/strings.cpp index b4ce13926e..43748f0109 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -197,7 +197,7 @@ void CopyOutDParam(uint64 *dst, const char **strings, StringID string, int num) } } -static void StationGetSpecialString(StringBuilder &builder, int x); +static void StationGetSpecialString(StringBuilder &builder, StationFacility x); static void GetSpecialTownNameString(StringBuilder &builder, int ind, uint32 seed); static void GetSpecialNameString(StringBuilder &builder, int ind, StringParameters &args); @@ -261,7 +261,7 @@ void GetStringWithArgs(StringBuilder &builder, StringID string, StringParameters switch (tab) { case TEXT_TAB_TOWN: if (index >= 0xC0 && !game_script) { - GetSpecialTownNameString(builder, index - 0xC0, args.GetInt32()); + GetSpecialTownNameString(builder, index - 0xC0, args.GetNextParameter()); return; } break; @@ -412,7 +412,7 @@ static void FormatNoCommaNumber(StringBuilder &builder, int64 number) FormatNumber(builder, number, ""); } -static void FormatZerofillNumber(StringBuilder &builder, int64 number, int64 count) +static void FormatZerofillNumber(StringBuilder &builder, int64 number, int count) { FormatNumber(builder, number, "", count); } @@ -1008,7 +1008,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara } case SCC_NEWGRF_PRINT_WORD_STRING_ID: { - StringID substr = args.GetInt32(); + StringID substr = args.GetNextParameter(); str_stack.push(GetStringPtr(substr)); case_index = next_substr_case_index; next_substr_case_index = 0; @@ -1100,7 +1100,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara break; case SCC_RAW_STRING_POINTER: { // {RAW_STRING} - const char *raw_string = (const char *)(size_t)args.GetInt64(); + const char *raw_string = (const char *)(size_t)args.GetNextParameter(); /* raw_string can be(come) nullptr when the parameter is out of range and 0 is returned instead. */ if (raw_string == nullptr || (game_script && std::find(_game_script_raw_strings.begin(), _game_script_raw_strings.end(), raw_string) == _game_script_raw_strings.end())) { @@ -1112,7 +1112,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara } case SCC_STRING: {// {STRING} - StringID string_id = args.GetInt32(); + StringID string_id = args.GetNextParameter(); if (game_script && GetStringTab(string_id) != TEXT_TAB_GAMESCRIPT_START) break; /* It's prohibited for the included string to consume any arguments. */ StringParameters tmp_params(args, 0); @@ -1129,7 +1129,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara case SCC_STRING6: case SCC_STRING7: { // {STRING1..7} /* Strings that consume arguments */ - StringID string_id = args.GetInt32(); + StringID string_id = args.GetNextParameter(); if (game_script && GetStringTab(string_id) != TEXT_TAB_GAMESCRIPT_START) break; uint size = b - SCC_STRING1 + 1; if (game_script && size > args.GetDataLeft()) { @@ -1143,54 +1143,54 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara } case SCC_COMMA: // {COMMA} - FormatCommaNumber(builder, args.GetInt64()); + FormatCommaNumber(builder, args.GetNextParameter()); break; case SCC_DECIMAL: { // {DECIMAL} - int64 number = args.GetInt64(); - int digits = args.GetInt32(); + int64 number = args.GetNextParameter(); + int digits = args.GetNextParameter(); FormatCommaNumber(builder, number, digits); break; } case SCC_NUM: // {NUM} - FormatNoCommaNumber(builder, args.GetInt64()); + FormatNoCommaNumber(builder, args.GetNextParameter()); break; case SCC_ZEROFILL_NUM: { // {ZEROFILL_NUM} - int64 num = args.GetInt64(); - FormatZerofillNumber(builder, num, args.GetInt64()); + int64 num = args.GetNextParameter(); + FormatZerofillNumber(builder, num, args.GetNextParameter()); break; } case SCC_HEX: // {HEX} - FormatHexNumber(builder, (uint64)args.GetInt64()); + FormatHexNumber(builder, args.GetNextParameter()); break; case SCC_BYTES: // {BYTES} - FormatBytes(builder, args.GetInt64()); + FormatBytes(builder, args.GetNextParameter()); break; case SCC_CARGO_TINY: { // {CARGO_TINY} /* Tiny description of cargotypes. Layout: * param 1: cargo type * param 2: cargo count */ - CargoID cargo = args.GetInt32(); + CargoID cargo = args.GetNextParameter(); if (cargo >= CargoSpec::GetArraySize()) break; StringID cargo_str = CargoSpec::Get(cargo)->units_volume; int64 amount = 0; switch (cargo_str) { case STR_TONS: - amount = _units_weight[_settings_game.locale.units_weight].c.ToDisplay(args.GetInt64()); + amount = _units_weight[_settings_game.locale.units_weight].c.ToDisplay(args.GetNextParameter()); break; case STR_LITERS: - amount = _units_volume[_settings_game.locale.units_volume].c.ToDisplay(args.GetInt64()); + amount = _units_volume[_settings_game.locale.units_volume].c.ToDisplay(args.GetNextParameter()); break; default: { - amount = args.GetInt64(); + amount = args.GetNextParameter(); break; } } @@ -1203,21 +1203,21 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara /* Short description of cargotypes. Layout: * param 1: cargo type * param 2: cargo count */ - CargoID cargo = args.GetInt32(); + CargoID cargo = args.GetNextParameter(); if (cargo >= CargoSpec::GetArraySize()) break; StringID cargo_str = CargoSpec::Get(cargo)->units_volume; switch (cargo_str) { case STR_TONS: { assert(_settings_game.locale.units_weight < lengthof(_units_weight)); - auto tmp_params = MakeParameters(_units_weight[_settings_game.locale.units_weight].c.ToDisplay(args.GetInt64())); + auto tmp_params = MakeParameters(_units_weight[_settings_game.locale.units_weight].c.ToDisplay(args.GetNextParameter())); FormatString(builder, GetStringPtr(_units_weight[_settings_game.locale.units_weight].l), tmp_params); break; } case STR_LITERS: { assert(_settings_game.locale.units_volume < lengthof(_units_volume)); - auto tmp_params = MakeParameters(_units_volume[_settings_game.locale.units_volume].c.ToDisplay(args.GetInt64())); + auto tmp_params = MakeParameters(_units_volume[_settings_game.locale.units_volume].c.ToDisplay(args.GetNextParameter())); FormatString(builder, GetStringPtr(_units_volume[_settings_game.locale.units_volume].l), tmp_params); break; } @@ -1233,7 +1233,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara case SCC_CARGO_LONG: { // {CARGO_LONG} /* First parameter is cargo type, second parameter is cargo count */ - CargoID cargo = args.GetInt32(); + CargoID cargo = args.GetNextParameter(); if (IsValidCargoID(cargo) && cargo >= CargoSpec::GetArraySize()) break; StringID cargo_str = !IsValidCargoID(cargo) ? STR_QUANTITY_N_A : CargoSpec::Get(cargo)->quantifier; @@ -1243,7 +1243,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara } case SCC_CARGO_LIST: { // {CARGO_LIST} - CargoTypes cmask = args.GetInt64(); + CargoTypes cmask = args.GetNextParameter(); bool first = true; for (const auto &cs : _sorted_cargo_specs) { @@ -1267,35 +1267,35 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara } case SCC_CURRENCY_SHORT: // {CURRENCY_SHORT} - FormatGenericCurrency(builder, _currency, args.GetInt64(), true); + FormatGenericCurrency(builder, _currency, args.GetNextParameter(), true); break; case SCC_CURRENCY_LONG: // {CURRENCY_LONG} - FormatGenericCurrency(builder, _currency, args.GetInt64(), false); + FormatGenericCurrency(builder, _currency, args.GetNextParameter(), false); break; case SCC_DATE_TINY: // {DATE_TINY} - FormatTinyOrISODate(builder, args.GetInt32(), STR_FORMAT_DATE_TINY); + FormatTinyOrISODate(builder, args.GetNextParameter(), STR_FORMAT_DATE_TINY); break; case SCC_DATE_SHORT: // {DATE_SHORT} - FormatMonthAndYear(builder, args.GetInt32(), next_substr_case_index); + FormatMonthAndYear(builder, args.GetNextParameter(), next_substr_case_index); next_substr_case_index = 0; break; case SCC_DATE_LONG: // {DATE_LONG} - FormatYmdString(builder, args.GetInt32(), next_substr_case_index); + FormatYmdString(builder, args.GetNextParameter(), next_substr_case_index); next_substr_case_index = 0; break; case SCC_DATE_ISO: // {DATE_ISO} - FormatTinyOrISODate(builder, args.GetInt32(), STR_FORMAT_DATE_ISO); + FormatTinyOrISODate(builder, args.GetNextParameter(), STR_FORMAT_DATE_ISO); break; case SCC_FORCE: { // {FORCE} assert(_settings_game.locale.units_force < lengthof(_units_force)); const auto &x = _units_force[_settings_game.locale.units_force]; - auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetInt64()), x.decimal_places); + auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetNextParameter()), x.decimal_places); FormatString(builder, GetStringPtr(x.s), tmp_params); break; } @@ -1303,7 +1303,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara case SCC_HEIGHT: { // {HEIGHT} assert(_settings_game.locale.units_height < lengthof(_units_height)); const auto &x = _units_height[_settings_game.locale.units_height]; - auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetInt64()), x.decimal_places); + auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetNextParameter()), x.decimal_places); FormatString(builder, GetStringPtr(x.s), tmp_params); break; } @@ -1311,7 +1311,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara case SCC_POWER: { // {POWER} assert(_settings_game.locale.units_power < lengthof(_units_power)); const auto &x = _units_power[_settings_game.locale.units_power]; - auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetInt64()), x.decimal_places); + auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetNextParameter()), x.decimal_places); FormatString(builder, GetStringPtr(x.s), tmp_params); break; } @@ -1320,13 +1320,13 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara auto setting = _settings_game.locale.units_power * 3u + _settings_game.locale.units_weight; assert(setting < lengthof(_units_power_to_weight)); const auto &x = _units_power_to_weight[setting]; - auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetInt64()), x.decimal_places); + auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetNextParameter()), x.decimal_places); FormatString(builder, GetStringPtr(x.s), tmp_params); break; } case SCC_VELOCITY: { // {VELOCITY} - int64 arg = args.GetInt64(); + int64_t arg = args.GetNextParameter(); // Unpack vehicle type from packed argument to get desired units. VehicleType vt = static_cast(GB(arg, 56, 8)); byte units = GetVelocityUnits(vt); @@ -1340,7 +1340,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara case SCC_VOLUME_SHORT: { // {VOLUME_SHORT} assert(_settings_game.locale.units_volume < lengthof(_units_volume)); const auto &x = _units_volume[_settings_game.locale.units_volume]; - auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetInt64()), x.decimal_places); + auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetNextParameter()), x.decimal_places); FormatString(builder, GetStringPtr(x.s), tmp_params); break; } @@ -1348,7 +1348,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara case SCC_VOLUME_LONG: { // {VOLUME_LONG} assert(_settings_game.locale.units_volume < lengthof(_units_volume)); const auto &x = _units_volume[_settings_game.locale.units_volume]; - auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetInt64()), x.decimal_places); + auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetNextParameter()), x.decimal_places); FormatString(builder, GetStringPtr(x.l), tmp_params); break; } @@ -1356,7 +1356,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara case SCC_WEIGHT_SHORT: { // {WEIGHT_SHORT} assert(_settings_game.locale.units_weight < lengthof(_units_weight)); const auto &x = _units_weight[_settings_game.locale.units_weight]; - auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetInt64()), x.decimal_places); + auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetNextParameter()), x.decimal_places); FormatString(builder, GetStringPtr(x.s), tmp_params); break; } @@ -1364,13 +1364,13 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara case SCC_WEIGHT_LONG: { // {WEIGHT_LONG} assert(_settings_game.locale.units_weight < lengthof(_units_weight)); const auto &x = _units_weight[_settings_game.locale.units_weight]; - auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetInt64()), x.decimal_places); + auto tmp_params = MakeParameters(x.c.ToDisplay(args.GetNextParameter()), x.decimal_places); FormatString(builder, GetStringPtr(x.l), tmp_params); break; } case SCC_COMPANY_NAME: { // {COMPANY} - const Company *c = Company::GetIfValid(args.GetInt32()); + const Company *c = Company::GetIfValid(args.GetNextParameter()); if (c == nullptr) break; if (!c->name.empty()) { @@ -1384,7 +1384,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara } case SCC_COMPANY_NUM: { // {COMPANY_NUM} - CompanyID company = (CompanyID)args.GetInt32(); + CompanyID company = args.GetNextParameter(); /* Nothing is added for AI or inactive companies */ if (Company::IsValidHumanID(company)) { @@ -1395,14 +1395,14 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara } case SCC_DEPOT_NAME: { // {DEPOT} - VehicleType vt = (VehicleType)args.GetInt32(); + VehicleType vt = args.GetNextParameter(); if (vt == VEH_AIRCRAFT) { StringParameters tmp_params = StringParameters(args, 1); GetStringWithArgs(builder, STR_FORMAT_DEPOT_NAME_AIRCRAFT, tmp_params); break; } - const Depot *d = Depot::Get(args.GetInt32()); + const Depot *d = Depot::Get(args.GetNextParameter()); if (!d->name.empty()) { auto tmp_params = MakeParameters(d->name); GetStringWithArgs(builder, STR_JUST_RAW_STRING, tmp_params); @@ -1414,7 +1414,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara } case SCC_ENGINE_NAME: { // {ENGINE} - int64 arg = args.GetInt64(); + int64_t arg = args.GetNextParameter(); const Engine *e = Engine::GetIfValid(static_cast(arg)); if (e == nullptr) break; @@ -1446,7 +1446,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara } case SCC_GROUP_NAME: { // {GROUP} - const Group *g = Group::GetIfValid(args.GetInt32()); + const Group *g = Group::GetIfValid(args.GetNextParameter()); if (g == nullptr) break; if (!g->name.empty()) { @@ -1460,7 +1460,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara } case SCC_INDUSTRY_NAME: { // {INDUSTRY} - const Industry *i = Industry::GetIfValid(args.GetInt32()); + const Industry *i = Industry::GetIfValid(args.GetNextParameter()); if (i == nullptr) break; static bool use_cache = true; @@ -1482,7 +1482,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara } case SCC_PRESIDENT_NAME: { // {PRESIDENT_NAME} - const Company *c = Company::GetIfValid(args.GetInt32()); + const Company *c = Company::GetIfValid(args.GetNextParameter()); if (c == nullptr) break; if (!c->president_name.empty()) { @@ -1496,7 +1496,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara } case SCC_STATION_NAME: { // {STATION} - StationID sid = args.GetInt32(); + StationID sid = args.GetNextParameter(); const Station *st = Station::GetIfValid(sid); if (st == nullptr) { @@ -1536,7 +1536,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara } case SCC_TOWN_NAME: { // {TOWN} - const Town *t = Town::GetIfValid(args.GetInt32()); + const Town *t = Town::GetIfValid(args.GetNextParameter()); if (t == nullptr) break; static bool use_cache = true; @@ -1553,7 +1553,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara } case SCC_WAYPOINT_NAME: { // {WAYPOINT} - Waypoint *wp = Waypoint::GetIfValid(args.GetInt32()); + Waypoint *wp = Waypoint::GetIfValid(args.GetNextParameter()); if (wp == nullptr) break; if (!wp->name.empty()) { @@ -1569,7 +1569,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara } case SCC_VEHICLE_NAME: { // {VEHICLE} - const Vehicle *v = Vehicle::GetIfValid(args.GetInt32()); + const Vehicle *v = Vehicle::GetIfValid(args.GetNextParameter()); if (v == nullptr) break; if (!v->name.empty()) { @@ -1597,7 +1597,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara } case SCC_SIGN_NAME: { // {SIGN} - const Sign *si = Sign::GetIfValid(args.GetInt32()); + const Sign *si = Sign::GetIfValid(args.GetNextParameter()); if (si == nullptr) break; if (!si->name.empty()) { @@ -1611,12 +1611,12 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara } case SCC_STATION_FEATURES: { // {STATIONFEATURES} - StationGetSpecialString(builder, args.GetInt32()); + StationGetSpecialString(builder, args.GetNextParameter()); break; } case SCC_COLOUR: { // {COLOUR} - StringControlCode scc = (StringControlCode)(SCC_BLUE + args.GetInt32()); + StringControlCode scc = (StringControlCode)(SCC_BLUE + args.GetNextParameter()); if (IsInsideMM(scc, SCC_BLUE, SCC_COLOUR)) builder.Utf8Encode(scc); break; } @@ -1629,7 +1629,7 @@ static void FormatString(StringBuilder &builder, const char *str_arg, StringPara } -static void StationGetSpecialString(StringBuilder &builder, int x) +static void StationGetSpecialString(StringBuilder &builder, StationFacility x) { if ((x & FACIL_TRAIN) != 0) builder.Utf8Encode(SCC_TRAIN); if ((x & FACIL_TRUCK_STOP) != 0) builder.Utf8Encode(SCC_LORRY); @@ -1759,21 +1759,21 @@ static void GetSpecialNameString(StringBuilder &builder, int ind, StringParamete { switch (ind) { case 1: // not used - builder += _silly_company_names[std::min(args.GetInt32() & 0xFFFF, lengthof(_silly_company_names) - 1)]; + builder += _silly_company_names[std::min(args.GetNextParameter(), lengthof(_silly_company_names) - 1)]; return; case 2: // used for Foobar & Co company names - GenAndCoName(builder, args.GetInt32()); + GenAndCoName(builder, args.GetNextParameter()); return; case 3: // President name - GenPresidentName(builder, args.GetInt32()); + GenPresidentName(builder, args.GetNextParameter()); return; } /* town name? */ if (IsInsideMM(ind - 6, 0, SPECSTR_TOWNNAME_LAST - SPECSTR_TOWNNAME_START + 1)) { - GetSpecialTownNameString(builder, ind - 6, args.GetInt32()); + GetSpecialTownNameString(builder, ind - 6, args.GetNextParameter()); builder += " Transport"; return; } From 7ad487eeeed417883b6b12def09f07f88039c4b7 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Thu, 22 Jun 2023 17:17:25 +0200 Subject: [PATCH 06/21] Cleanup: remove now unused GetInt32/64 functions --- src/strings_internal.h | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/strings_internal.h b/src/strings_internal.h index c79551fde8..e214a3c1a1 100644 --- a/src/strings_internal.h +++ b/src/strings_internal.h @@ -92,17 +92,6 @@ public: return static_cast(ptr == nullptr ? 0 : ptr->data); } - int64 GetInt64() - { - return GetNextParameter(); - } - - /** Read an int32 from the argument array. @see GetInt64. */ - int32 GetInt32() - { - return GetNextParameter(); - } - /** * Get a new instance of StringParameters that is a "range" into the * remaining existing parameters. Upon destruction the offset in the parent From 700241410b770d51b0b459f4490b6f846e3a11fe Mon Sep 17 00:00:00 2001 From: Rubidium Date: Thu, 22 Jun 2023 21:22:45 +0200 Subject: [PATCH 07/21] Remove: support for not having getifaddrs --- src/network/core/host.cpp | 68 ++++++------------------------- src/network/core/os_abstraction.h | 10 +---- 2 files changed, 13 insertions(+), 65 deletions(-) diff --git a/src/network/core/host.cpp b/src/network/core/host.cpp index 6644e95297..4d57dcb501 100644 --- a/src/network/core/host.cpp +++ b/src/network/core/host.cpp @@ -21,25 +21,7 @@ */ static void NetworkFindBroadcastIPsInternal(NetworkAddressList *broadcast); -#if defined(HAVE_GETIFADDRS) -static void NetworkFindBroadcastIPsInternal(NetworkAddressList *broadcast) // GETIFADDRS implementation -{ - struct ifaddrs *ifap, *ifa; - - if (getifaddrs(&ifap) != 0) return; - - for (ifa = ifap; ifa != nullptr; ifa = ifa->ifa_next) { - if (!(ifa->ifa_flags & IFF_BROADCAST)) continue; - if (ifa->ifa_broadaddr == nullptr) continue; - if (ifa->ifa_broadaddr->sa_family != AF_INET) continue; - - NetworkAddress addr(ifa->ifa_broadaddr, sizeof(sockaddr)); - if (std::none_of(broadcast->begin(), broadcast->end(), [&addr](NetworkAddress const& elem) -> bool { return elem == addr; })) broadcast->push_back(addr); - } - freeifaddrs(ifap); -} - -#elif defined(_WIN32) +#ifdef _WIN32 static void NetworkFindBroadcastIPsInternal(NetworkAddressList *broadcast) // Win32 implementation { SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0); @@ -77,48 +59,22 @@ static void NetworkFindBroadcastIPsInternal(NetworkAddressList *broadcast) // Wi closesocket(sock); } -#else /* not HAVE_GETIFADDRS */ - -#include "../../string_func.h" - -static void NetworkFindBroadcastIPsInternal(NetworkAddressList *broadcast) // !GETIFADDRS implementation +#else /* not WIN32 */ +static void NetworkFindBroadcastIPsInternal(NetworkAddressList *broadcast) { - SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock == INVALID_SOCKET) return; - - char buf[4 * 1024]; // Arbitrary buffer size - struct ifconf ifconf; - - ifconf.ifc_len = sizeof(buf); - ifconf.ifc_buf = buf; - if (ioctl(sock, SIOCGIFCONF, &ifconf) == -1) { - closesocket(sock); - return; - } - - const char *buf_end = buf + ifconf.ifc_len; - for (const char *p = buf; p < buf_end;) { - const struct ifreq *req = (const struct ifreq*)p; + struct ifaddrs *ifap, *ifa; - if (req->ifr_addr.sa_family == AF_INET) { - struct ifreq r; + if (getifaddrs(&ifap) != 0) return; - strecpy(r.ifr_name, req->ifr_name, lastof(r.ifr_name)); - if (ioctl(sock, SIOCGIFFLAGS, &r) != -1 && - (r.ifr_flags & IFF_BROADCAST) && - ioctl(sock, SIOCGIFBRDADDR, &r) != -1) { - NetworkAddress addr(&r.ifr_broadaddr, sizeof(sockaddr)); - if (std::none_of(broadcast->begin(), broadcast->end(), [&addr](NetworkAddress const& elem) -> bool { return elem == addr; })) broadcast->push_back(addr); - } - } + for (ifa = ifap; ifa != nullptr; ifa = ifa->ifa_next) { + if (!(ifa->ifa_flags & IFF_BROADCAST)) continue; + if (ifa->ifa_broadaddr == nullptr) continue; + if (ifa->ifa_broadaddr->sa_family != AF_INET) continue; - p += sizeof(struct ifreq); -#if defined(AF_LINK) && !defined(SUNOS) - p += req->ifr_addr.sa_len - sizeof(struct sockaddr); -#endif + NetworkAddress addr(ifa->ifa_broadaddr, sizeof(sockaddr)); + if (std::none_of(broadcast->begin(), broadcast->end(), [&addr](NetworkAddress const& elem) -> bool { return elem == addr; })) broadcast->push_back(addr); } - - closesocket(sock); + freeifaddrs(ifap); } #endif /* all NetworkFindBroadcastIPsInternals */ diff --git a/src/network/core/os_abstraction.h b/src/network/core/os_abstraction.h index 461ada2b12..c8cf67a499 100644 --- a/src/network/core/os_abstraction.h +++ b/src/network/core/os_abstraction.h @@ -78,15 +78,7 @@ typedef unsigned long in_addr_t; # include # include # include -/* According to glibc/NEWS, appeared in glibc-2.3. */ -# if !defined(__sgi__) && !defined(SUNOS) \ - && !(defined(__GLIBC__) && (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 2)) && !defined(__dietlibc__) && !defined(HPUX) -/* If for any reason ifaddrs.h does not exist on your system, comment out - * the following two lines and an alternative way will be used to fetch - * the list of IPs from the system. */ -# include -# define HAVE_GETIFADDRS -# endif +# include # if !defined(INADDR_NONE) # define INADDR_NONE 0xffffffff # endif From 794b642b9abea7ac985cb4a7664281631db69fca Mon Sep 17 00:00:00 2001 From: Rubidium Date: Wed, 21 Jun 2023 20:04:59 +0200 Subject: [PATCH 08/21] Codechange: use std::string/std::vector over stredup/strecpy/CallocT/free --- src/music/extmidi.cpp | 49 +++++++++++++++++++------------------------ src/music/extmidi.h | 4 ++-- 2 files changed, 24 insertions(+), 29 deletions(-) diff --git a/src/music/extmidi.cpp b/src/music/extmidi.cpp index 69dd259d8a..32fce42e2c 100644 --- a/src/music/extmidi.cpp +++ b/src/music/extmidi.cpp @@ -49,37 +49,25 @@ const char *MusicDriver_ExtMidi::Start(const StringList &parm) if (StrEmpty(command)) command = EXTERNAL_PLAYER " " MIDI_ARG; #endif - /* Count number of arguments, but include 3 extra slots: 1st for command, 2nd for song title, and 3rd for terminating nullptr. */ - uint num_args = 3; - for (const char *t = command; *t != '\0'; t++) if (*t == ' ') num_args++; - - this->params = CallocT(num_args); - this->params[0] = stredup(command); - - /* Replace space with \0 and add next arg to params */ - uint p = 1; - while (true) { - this->params[p] = strchr(this->params[p - 1], ' '); - if (this->params[p] == nullptr) break; - - this->params[p][0] = '\0'; - this->params[p]++; - p++; - } + this->command_tokens.clear(); + + std::string_view view = command; + for (;;) { + auto pos = view.find(' '); + this->command_tokens.emplace_back(view.substr(0, pos)); - /* Last parameter is the song file. */ - this->params[p] = this->song; + if (pos == std::string_view::npos) break; + view.remove_prefix(pos + 1); + } - this->song[0] = '\0'; + this->song.clear(); this->pid = -1; return nullptr; } void MusicDriver_ExtMidi::Stop() { - free(params[0]); - free(params); - this->song[0] = '\0'; + this->song.clear(); this->DoStop(); } @@ -87,14 +75,14 @@ void MusicDriver_ExtMidi::PlaySong(const MusicSongInfo &song) { std::string filename = MidiFile::GetSMFFile(song); if (!filename.empty()) { - strecpy(this->song, filename.c_str(), lastof(this->song)); + this->song = std::move(filename); this->DoStop(); } } void MusicDriver_ExtMidi::StopSong() { - this->song[0] = '\0'; + this->song.clear(); this->DoStop(); } @@ -103,7 +91,7 @@ bool MusicDriver_ExtMidi::IsSongPlaying() if (this->pid != -1 && waitpid(this->pid, nullptr, WNOHANG) == this->pid) { this->pid = -1; } - if (this->pid == -1 && this->song[0] != '\0') this->DoPlay(); + if (this->pid == -1 && !this->song.empty()) this->DoPlay(); return this->pid != -1; } @@ -120,7 +108,14 @@ void MusicDriver_ExtMidi::DoPlay() close(0); int d = open("/dev/null", O_RDONLY); if (d != -1 && dup2(d, 1) != -1 && dup2(d, 2) != -1) { - execvp(this->params[0], this->params); + /* execvp is nasty as it *allows* the passed parameters to be written + * for backward compatibility, however we are a fork so do not care. */ + std::vector parameters; + for (auto &token : this->command_tokens) parameters.emplace_back(token.data()); + parameters.emplace_back(this->song.data()); + parameters.emplace_back(nullptr); + + execvp(parameters[0], parameters.data()); } _exit(1); } diff --git a/src/music/extmidi.h b/src/music/extmidi.h index f43bbad179..b106ef91f8 100644 --- a/src/music/extmidi.h +++ b/src/music/extmidi.h @@ -14,8 +14,8 @@ class MusicDriver_ExtMidi : public MusicDriver { private: - char **params; - char song[MAX_PATH]; + std::vector command_tokens; + std::string song; pid_t pid; void DoPlay(); From 8465559488fce68c76b265b220aed58e1c8683fc Mon Sep 17 00:00:00 2001 From: PeterN Date: Tue, 27 Jun 2023 12:30:46 +0100 Subject: [PATCH 09/21] Codechange: Pass face index as font os_handle for FreeType fonts. (#11073) This allows fallback font detection to test the specific face within the font rather instead of only the first. --- src/fontcache/freetypefontcache.cpp | 4 +++- src/os/unix/font_unix.cpp | 15 +++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/fontcache/freetypefontcache.cpp b/src/fontcache/freetypefontcache.cpp index 65b1185435..7fbf52e97c 100644 --- a/src/fontcache/freetypefontcache.cpp +++ b/src/fontcache/freetypefontcache.cpp @@ -141,7 +141,9 @@ void LoadFreeTypeFont(FontSize fs) FT_Face face = nullptr; /* If font is an absolute path to a ttf, try loading that first. */ - FT_Error error = FT_New_Face(_library, font_name, 0, &face); + int32_t index = 0; + if (settings->os_handle != nullptr) index = *static_cast(settings->os_handle); + FT_Error error = FT_New_Face(_library, font_name, index, &face); if (error != FT_Err_Ok) { /* Check if font is a relative filename in one of our search-paths. */ diff --git a/src/os/unix/font_unix.cpp b/src/os/unix/font_unix.cpp index 9b58e6d8a4..9e08aecdb7 100644 --- a/src/os/unix/font_unix.cpp +++ b/src/os/unix/font_unix.cpp @@ -111,8 +111,8 @@ bool SetFallbackFont(FontCacheSettings *settings, const std::string &language_is /* First create a pattern to match the wanted language. */ FcPattern *pat = FcNameParse((const FcChar8 *)lang.c_str()); - /* We only want to know the filename. */ - FcObjectSet *os = FcObjectSetBuild(FC_FILE, FC_SPACING, FC_SLANT, FC_WEIGHT, nullptr); + /* We only want to know these attributes. */ + FcObjectSet *os = FcObjectSetBuild(FC_FILE, FC_INDEX, FC_SPACING, FC_SLANT, FC_WEIGHT, nullptr); /* Get the list of filenames matching the wanted language. */ FcFontSet *fs = FcFontList(nullptr, pat, os); @@ -123,6 +123,7 @@ bool SetFallbackFont(FontCacheSettings *settings, const std::string &language_is if (fs != nullptr) { int best_weight = -1; const char *best_font = nullptr; + int best_index = 0; for (int i = 0; i < fs->nfont; i++) { FcPattern *font = fs->fonts[i]; @@ -146,7 +147,12 @@ bool SetFallbackFont(FontCacheSettings *settings, const std::string &language_is FcPatternGetInteger(font, FC_WEIGHT, 0, &value); if (value <= best_weight) continue; - callback->SetFontNames(settings, (const char *)file); + /* Possible match based on attributes, get index. */ + int32_t index; + res = FcPatternGetInteger(font, FC_INDEX, 0, &index); + if (res != FcResultMatch) continue; + + callback->SetFontNames(settings, (const char *)file, &index); bool missing = callback->FindMissingGlyphs(); Debug(fontcache, 1, "Font \"{}\" misses{} glyphs", (char *)file, missing ? "" : " no"); @@ -154,12 +160,13 @@ bool SetFallbackFont(FontCacheSettings *settings, const std::string &language_is if (!missing) { best_weight = value; best_font = (const char *)file; + best_index = index; } } if (best_font != nullptr) { ret = true; - callback->SetFontNames(settings, best_font); + callback->SetFontNames(settings, best_font, &best_index); InitFontCache(callback->Monospace()); } From 55c07eed597c0e09d88ec0ca73427d8a70c0e391 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Tue, 27 Jun 2023 12:32:45 +0100 Subject: [PATCH 10/21] Change: Add separate setting for server sent commands per frame limit (#11023) Set a higher default value for this setting. Use the higher of this and existing commands per frame limit setting for server-originating commands, e.g. GS. This is to support the GSAsyncMode class. This also avoids undue throttling when more than one script is in operation (e.g. AIs). --- src/network/network_command.cpp | 4 ++++ src/settings_type.h | 1 + src/table/settings/network_settings.ini | 9 +++++++++ 3 files changed, 14 insertions(+) diff --git a/src/network/network_command.cpp b/src/network/network_command.cpp index 30b3bde67a..27477ea9a4 100644 --- a/src/network/network_command.cpp +++ b/src/network/network_command.cpp @@ -392,6 +392,10 @@ static void DistributeQueue(CommandQueue *queue, const NetworkClientSocket *owne int to_go = UINT16_MAX; #else int to_go = _settings_client.network.commands_per_frame; + if (owner == nullptr) { + /* This is the server, use the commands_per_frame_server setting if higher */ + to_go = std::max(to_go, _settings_client.network.commands_per_frame_server); + } #endif CommandPacket *cp; diff --git a/src/settings_type.h b/src/settings_type.h index 5b97fa78dc..739d4d8798 100644 --- a/src/settings_type.h +++ b/src/settings_type.h @@ -279,6 +279,7 @@ struct NetworkSettings { uint16 sync_freq; ///< how often do we check whether we are still in-sync uint8 frame_freq; ///< how often do we send commands to the clients uint16 commands_per_frame; ///< how many commands may be sent each frame_freq frames? + uint16 commands_per_frame_server; ///< how many commands may be sent each frame_freq frames? (server-originating commands) uint16 max_commands_in_queue; ///< how many commands may there be in the incoming queue before dropping the connection? uint16 bytes_per_frame; ///< how many bytes may, over a long period, be received per frame? uint16 bytes_per_frame_burst; ///< how many bytes may, over a short period, be received? diff --git a/src/table/settings/network_settings.ini b/src/table/settings/network_settings.ini index 860eb26cec..3ec38ac8e7 100644 --- a/src/table/settings/network_settings.ini +++ b/src/table/settings/network_settings.ini @@ -66,6 +66,15 @@ min = 1 max = 65535 cat = SC_EXPERT +[SDTC_VAR] +var = network.commands_per_frame_server +type = SLE_UINT16 +flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_NETWORK_ONLY +def = 16 +min = 1 +max = 65535 +cat = SC_EXPERT + [SDTC_VAR] var = network.max_commands_in_queue type = SLE_UINT16 From 5b0cfc7ea5a1c257b2a8a07e22ccd379c5637fe4 Mon Sep 17 00:00:00 2001 From: "Johannes E. Krause" Date: Tue, 27 Jun 2023 12:46:14 +0200 Subject: [PATCH 11/21] Add: show fallback sprites with debuglevel sprite=4 --- src/gfxinit.cpp | 1 + src/spritecache.cpp | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp index 3ebead6daa..198787be4f 100644 --- a/src/gfxinit.cpp +++ b/src/gfxinit.cpp @@ -213,6 +213,7 @@ static void LoadSpriteTables() LoadNewGRF(SPR_NEWGRFS_BASE, 2); uint total_extra_graphics = SPR_NEWGRFS_BASE - SPR_OPENTTD_BASE; + Debug(sprite, 4, "Checking sprites from fallback grf"); _missing_extra_graphics = GetSpriteCountForFile(master_filename, SPR_OPENTTD_BASE, SPR_NEWGRFS_BASE); Debug(sprite, 1, "{} extra sprites, {} from baseset, {} from fallback", total_extra_graphics, total_extra_graphics - _missing_extra_graphics, _missing_extra_graphics); diff --git a/src/spritecache.cpp b/src/spritecache.cpp index a110ce6322..e5acc50b66 100644 --- a/src/spritecache.cpp +++ b/src/spritecache.cpp @@ -205,7 +205,10 @@ uint GetSpriteCountForFile(const std::string &filename, SpriteID begin, SpriteID for (SpriteID i = begin; i != end; i++) { if (SpriteExists(i)) { SpriteCache *sc = GetSpriteCache(i); - if (sc->file == file) count++; + if (sc->file == file) { + count++; + Debug(sprite, 4, "Sprite: {}", i); + } } } return count; @@ -731,7 +734,7 @@ void IncreaseSpriteLRU() if (_sprite_lru_counter > 16384) { SpriteID i; - Debug(sprite, 3, "Fixing lru {}, inuse={}", _sprite_lru_counter, GetSpriteCacheUsage()); + Debug(sprite, 5, "Fixing lru {}, inuse={}", _sprite_lru_counter, GetSpriteCacheUsage()); for (i = 0; i != _spritecache_items; i++) { SpriteCache *sc = GetSpriteCache(i); From 3b2934c479ed3e23a01e6753bc7788012e3440df Mon Sep 17 00:00:00 2001 From: Richard Wheeler <2762690+zephyris@users.noreply.github.com> Date: Tue, 27 Jun 2023 15:47:42 +0100 Subject: [PATCH 12/21] Change: Make terraforming point selection sprite visible at >2x zoom out (#11017) --- src/smallmap_gui.cpp | 2 +- src/table/sprites.h | 2 +- src/viewport.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/smallmap_gui.cpp b/src/smallmap_gui.cpp index c98fee110a..3917cb6057 100644 --- a/src/smallmap_gui.cpp +++ b/src/smallmap_gui.cpp @@ -1800,7 +1800,7 @@ static const NWidgetPart _nested_smallmap_bar[] = { NWidget(WWT_PUSHIMGBTN, COLOUR_BROWN, WID_SM_CENTERMAP), SetDataTip(SPR_IMG_SMALLMAP, STR_SMALLMAP_CENTER), SetFill(1, 1), NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_BLANK), - SetDataTip(SPR_DOT_SMALL, STR_NULL), SetFill(1, 1), + SetDataTip(SPR_EMPTY, STR_NULL), SetFill(1, 1), NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_CONTOUR), SetDataTip(SPR_IMG_SHOW_COUNTOURS, STR_SMALLMAP_TOOLTIP_SHOW_LAND_CONTOURS_ON_MAP), SetFill(1, 1), NWidget(WWT_IMGBTN, COLOUR_BROWN, WID_SM_VEHICLES), diff --git a/src/table/sprites.h b/src/table/sprites.h index 907d37fdcc..504db6e446 100644 --- a/src/table/sprites.h +++ b/src/table/sprites.h @@ -42,7 +42,7 @@ static const SpriteID SPR_SELECT_TILE = 752; static const SpriteID SPR_DOT = 774; // corner marker for lower/raise land -static const SpriteID SPR_DOT_SMALL = 4078; +static const SpriteID SPR_EMPTY = 4078; // empty (transparent blue) sprite static const SpriteID SPR_WHITE_POINT = 4079; /* ASCII */ diff --git a/src/viewport.cpp b/src/viewport.cpp index b7bea78832..2165d15fcf 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -1126,7 +1126,7 @@ draw_inner: if (IsSteepSlope(ti->tileh)) z -= TILE_HEIGHT; } } - DrawSelectionSprite(_cur_dpi->zoom <= ZOOM_LVL_DETAIL ? SPR_DOT : SPR_DOT_SMALL, PAL_NONE, ti, z, foundation_part); + DrawSelectionSprite(SPR_DOT, PAL_NONE, ti, z, foundation_part); } else if (_thd.drawstyle & HT_RAIL) { /* autorail highlight piece under cursor */ HighLightStyle type = _thd.drawstyle & HT_DIR_MASK; From 55979b612e91eb3c986190e5b7438bb1566da01f Mon Sep 17 00:00:00 2001 From: translators Date: Tue, 27 Jun 2023 18:43:13 +0000 Subject: [PATCH 13/21] Update: Translations from eints welsh: 28 changes by Ansbaradigeidfran portuguese: 1 change by azulcosta polish: 1 change by pAter-exe --- src/lang/polish.txt | 1 + src/lang/portuguese.txt | 1 + src/lang/welsh.txt | 33 ++++++++++++++++++++++++++++----- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/lang/polish.txt b/src/lang/polish.txt index 7176edacae..9e14dca33d 100644 --- a/src/lang/polish.txt +++ b/src/lang/polish.txt @@ -1331,6 +1331,7 @@ STR_GAME_OPTIONS_VOLUME_100 :100% STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME :{BLACK}Waluta STR_GAME_OPTIONS_CURRENCY_UNITS_DROPDOWN_TOOLTIP :{BLACK}Wybór waluty +STR_GAME_OPTIONS_CURRENCY_CODE :{STRING} ({STRING}) ###length 42 STR_GAME_OPTIONS_CURRENCY_GBP :Funt brytyjski diff --git a/src/lang/portuguese.txt b/src/lang/portuguese.txt index dcde1bb52e..199599dd9c 100644 --- a/src/lang/portuguese.txt +++ b/src/lang/portuguese.txt @@ -952,6 +952,7 @@ STR_GAME_OPTIONS_VOLUME_100 :100% STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME :{BLACK}Unidades monetárias STR_GAME_OPTIONS_CURRENCY_UNITS_DROPDOWN_TOOLTIP :{BLACK}Selecção de unidades monetárias +STR_GAME_OPTIONS_CURRENCY_CODE :{STRING} ({STRING}) ###length 42 STR_GAME_OPTIONS_CURRENCY_GBP :Libra Britânica diff --git a/src/lang/welsh.txt b/src/lang/welsh.txt index 24303ae30f..60e6b99989 100644 --- a/src/lang/welsh.txt +++ b/src/lang/welsh.txt @@ -732,7 +732,7 @@ STR_SMALLMAP_LEGENDA_FOREST :{TINY_FONT}{BLA STR_SMALLMAP_LEGENDA_RAILROAD_STATION :{TINY_FONT}{BLACK}Gorsaf Reilffordd STR_SMALLMAP_LEGENDA_TRUCK_LOADING_BAY :{TINY_FONT}{BLACK}Man Llwytho Lorïau STR_SMALLMAP_LEGENDA_BUS_STATION :{TINY_FONT}{BLACK}Gorsaf Fysiau -STR_SMALLMAP_LEGENDA_AIRPORT_HELIPORT :{TINY_FONT}{BLACK}Maes Awyr/Glanfa Hofrenyddion +STR_SMALLMAP_LEGENDA_AIRPORT_HELIPORT :{TINY_FONT}{BLACK}Maes Awyr/Hofrenfa STR_SMALLMAP_LEGENDA_DOCK :{TINY_FONT}{BLACK}Doc STR_SMALLMAP_LEGENDA_ROUGH_LAND :{TINY_FONT}{BLACK}Tir Garw STR_SMALLMAP_LEGENDA_GRASS_LAND :{TINY_FONT}{BLACK}Glaswelltir @@ -771,6 +771,7 @@ STR_STATUSBAR_PAUSED :{YELLOW}* * WE STR_STATUSBAR_AUTOSAVE :{RED}AWTOGADW STR_STATUSBAR_SAVING_GAME :{RED}* * CADW GÊM * * +STR_STATUSBAR_SPECTATOR :{WHITE}(gwyliwr) # News message history STR_MESSAGE_HISTORY :{WHITE}Hanes Negeseuon @@ -872,7 +873,12 @@ STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}Mae {STA STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Cynnig cymhorthdal ar ben:{}{}Ni fydd cludo {STRING} o {STRING} i {STRING} yn derbyn cymhorthdal bellach STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Cymhorthdal wedi'i dynnu'n ôl:{}{}Ni fydd gwasanaeth {STRING} o {STRING} i {STRING} yn derbyn cymhorthdal bellach +STR_NEWS_SERVICE_SUBSIDY_OFFERED :{BIG_FONT}{BLACK}Cynnig cymhorthdal:{}{}Bydd y gwasanaeth {STRING} cyntaf o {STRING} i {STRING} yn derbyn {NUM} {P "blwyddyn" "mlynedd"}! o gymhorthdal gan yr awdurdod lleol! ###length 4 +STR_NEWS_SERVICE_SUBSIDY_AWARDED_HALF :{BIG_FONT}{BLACK}Cymhorthdal wedi ei ddyfarnu i {STRING}!{}{}Bydd y gwasanaeth {STRING} o {STRING} i {STRING} yn talu 50% yn fwy am {NUM} {P "blwyddyn" "mlynedd"}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_DOUBLE :{BIG_FONT}{BLACK}Cymhorthdal wedi ei ddyfarnu i {STRING}!{}{}Bydd y gwasanaeth {STRING} o {STRING} i {STRING} yn talu dwywaith yn fwy am {NUM} {P "blwyddyn" "mlynedd"}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_TRIPLE :{BIG_FONT}{BLACK}Cymhorthdal wedi ei ddyfarnu i {STRING}!{}{}Bydd y gwasanaeth {STRING} o {STRING} i {STRING} yn talu teirgwaith yn fwy am {NUM} {P "blwyddyn" "mlynedd"}! +STR_NEWS_SERVICE_SUBSIDY_AWARDED_QUADRUPLE :{BIG_FONT}{BLACK}Cymhorthdal wedi ei ddyfarnu i {STRING}!{}{}Bydd y gwasanaeth {STRING} o {STRING} i {STRING} yn talu pedair gwaith yn fwy am {NUM} {P "blwyddyn" "mlynedd"}! STR_NEWS_ROAD_REBUILDING :{BIG_FONT}{BLACK}Anrhefn traffig yn {TOWN}!{}{}Daw gwaith ffordd a ariannwyd gan {STRING} â 6 mis o boen i deithwyr ffordd y dref! STR_NEWS_EXCLUSIVE_RIGHTS_TITLE :{BIG_FONT}{BLACK}Monopoli cludiant! @@ -890,6 +896,7 @@ STR_GAME_OPTIONS_CAPTION :{WHITE}Dewisiad +STR_GAME_OPTIONS_VOLUME_50 :50% STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME :{BLACK}Uned Arian STR_GAME_OPTIONS_CURRENCY_UNITS_DROPDOWN_TOOLTIP :{BLACK}Dewis unedau arian @@ -955,6 +962,7 @@ STR_GAME_OPTIONS_RESOLUTION_OTHER :arall +STR_GAME_OPTIONS_GUI_SCALE_5X :5x @@ -1366,6 +1374,7 @@ STR_CONFIG_SETTING_OIL_REF_EDGE_DISTANCE_HELPTEXT :Codir purfeydd STR_CONFIG_SETTING_SNOWLINE_HEIGHT :Uchder Llinell Eira: {STRING} STR_CONFIG_SETTING_SNOWLINE_HEIGHT_HELPTEXT :Rheoli'r uchder y mae eira'n ymddangos mewn tirwedd is-arctig. Mae eira hefyd yn effeitiho ar gynhyrchu diwydiannau a gofynion twf trefi +STR_CONFIG_SETTING_SNOW_COVERAGE_VALUE :{NUM}% STR_CONFIG_SETTING_ROUGHNESS_OF_TERRAIN :Garwder y tirwedd: {STRING} @@ -1933,6 +1942,7 @@ STR_INTRO_TRANSLATION :{BLACK}Mae'r cy # Quit window STR_QUIT_CAPTION :{WHITE}Gadael +STR_QUIT_ARE_YOU_SURE_YOU_WANT_TO_EXIT_OPENTTD :{YELLOW}Ydych chi'n siŵr eich bod eisiau gadael OpenTTD? STR_QUIT_YES :{BLACK}Iawn STR_QUIT_NO :{BLACK}Na @@ -2251,6 +2261,7 @@ STR_NETWORK_MESSAGE_CLIENT_COMPANY_SPECTATE :*** Mae {STRING STR_NETWORK_MESSAGE_CLIENT_COMPANY_NEW :*** Mae {STRING} wedi dechrau cwmni newydd (#{2:NUM}) STR_NETWORK_MESSAGE_CLIENT_LEFT :*** Mae {STRING} wedi gadael y gêm ({2:STRING}) STR_NETWORK_MESSAGE_NAME_CHANGE :*** Mae {STRING} wedi newid ei (h)enw i {STRING} +STR_NETWORK_MESSAGE_GIVE_MONEY :*** Rhoddodd {0:STRING} {2:CURRENCY_LONG} i {1:STRING} STR_NETWORK_MESSAGE_SERVER_SHUTDOWN :{WHITE}Fe gaewyd y sesiwn gan y gweinydd STR_NETWORK_MESSAGE_SERVER_REBOOT :{WHITE}Mae'r gweinydd yn ailgychwyn...{}Arhoswch... @@ -2374,6 +2385,7 @@ STR_JOIN_WAYPOINT_CAPTION :{WHITE}Uno pwyn STR_JOIN_WAYPOINT_CREATE_SPLITTED_WAYPOINT :{YELLOW}Adeiladu pwynt llwybro annibynnol # Generic toolbar +STR_TOOLBAR_DISABLED_NO_VEHICLE_AVAILABLE :{BLACK}Analluogwyd gan nad oes cerbydau ar gael i'r tanadeiledd yma ar hyn o bryd # Rail construction toolbar STR_RAIL_TOOLBAR_RAILROAD_CONSTRUCTION_CAPTION :Adeiladu Rheilffyrdd @@ -2528,14 +2540,14 @@ STR_AIRPORT_METRO :Maes awyr metro STR_AIRPORT_INTERNATIONAL :Rhyngwladol STR_AIRPORT_COMMUTER :Cymudol STR_AIRPORT_INTERCONTINENTAL :Rhyng-gyfandirol -STR_AIRPORT_HELIPORT :Porth Hofrennydd +STR_AIRPORT_HELIPORT :Hofrenfa STR_AIRPORT_HELIDEPOT :Depo Hofrennydd STR_AIRPORT_HELISTATION :Gorsaf Hofrennydd STR_AIRPORT_CLASS_SMALL :Meysydd awyr bach STR_AIRPORT_CLASS_LARGE :Meysydd awyr mawr STR_AIRPORT_CLASS_HUB :Meysydd awyr cyfnewid -STR_AIRPORT_CLASS_HELIPORTS :Meysydd awyr hofrennydd +STR_AIRPORT_CLASS_HELIPORTS :Hofrenfeydd STR_STATION_BUILD_NOISE :{BLACK}Swn a gynhyrchir: {GOLD}{COMMA} @@ -2619,6 +2631,7 @@ STR_FUND_INDUSTRY_INDUSTRY_BUILD_COST :{BLACK}Côst: { STR_FUND_INDUSTRY_PROSPECT_NEW_INDUSTRY :{BLACK}Mwynchwilio STR_FUND_INDUSTRY_BUILD_NEW_INDUSTRY :{BLACK}Adeiladu STR_FUND_INDUSTRY_FUND_NEW_INDUSTRY :{BLACK}Ariannu +STR_FUND_INDUSTRY_REMOVE_ALL_INDUSTRIES_QUERY :{YELLOW}Ydych chi'n siŵr eich bod eisiau dileu pob diwydiant? # Industry cargoes window STR_INDUSTRY_CARGOES_INDUSTRY_CAPTION :{WHITE}Cadwyn ddiwydiant ar gyfer diwydiant {STRING} @@ -2799,6 +2812,7 @@ STR_SAVELOAD_DETAIL_CAPTION :{BLACK}Manylion STR_SAVELOAD_DETAIL_NOT_AVAILABLE :{BLACK}Dim gwybodaeth ar gael STR_SAVELOAD_DETAIL_COMPANY_INDEX :{SILVER}{COMMA}: {WHITE}{STRING} STR_SAVELOAD_DETAIL_GRFSTATUS :{SILVER}NewGRF: {WHITE}{STRING} +STR_SAVELOAD_PARENT_DIRECTORY :{STRING} (Plygell rhiant) STR_SAVELOAD_OSKTITLE :{BLACK}Rhowch enw ar gyfer y gêm a gadwyd @@ -2859,6 +2873,7 @@ STR_MAPGEN_HEIGHTMAP_NAME :{BLACK}Enw'r Ma STR_MAPGEN_HEIGHTMAP_SIZE_LABEL :{BLACK}Maint: STR_MAPGEN_HEIGHTMAP_SIZE :{ORANGE}{NUM} x {NUM} +STR_MAPGEN_SNOW_COVERAGE_QUERY_CAPT :{WHITE}Gorchudd eira (mewn %) STR_MAPGEN_START_DATE_QUERY_CAPT :{WHITE}Newid y flwyddyn gychwyn # SE Map generation @@ -2995,6 +3010,7 @@ STR_NEWGRF_ERROR_MSG_INFO :{SILVER}{STRING STR_NEWGRF_ERROR_MSG_WARNING :{RED}Rhybudd: {SILVER}{STRING} STR_NEWGRF_ERROR_MSG_ERROR :{RED}Gwall: {SILVER}{STRING} STR_NEWGRF_ERROR_MSG_FATAL :{RED}Angheuol: {SILVER}{STRING} +STR_NEWGRF_ERROR_FATAL_POPUP :{WHITE}Mae'r NewGRF "{STRING}" wedi dychwelyd gwall angheuol:{}{STRING} STR_NEWGRF_ERROR_VERSION_NUMBER :Ni fydd {1:STRING} yn gweithio gyda'r fersiwn o TTDPatch yr adroddir gan OpenTTD STR_NEWGRF_ERROR_DOS_OR_WINDOWS :Mae {1:STRING} ar gyfer y fersiwn {STRING} o TTD STR_NEWGRF_ERROR_UNSET_SWITCH :Mae {1:STRING} wedi ei gynllunio i gael ei ddefnyddio gyda {STRING} @@ -3141,6 +3157,7 @@ STR_LOCAL_AUTHORITY_ACTION_TOOLTIP_BRIBE :{YELLOW} Llwgrw # Goal window STR_GOALS_CAPTION :{WHITE}Amcanion {COMPANY} STR_GOALS_SPECTATOR_CAPTION :{WHITE}Amcanion Bydol +STR_GOALS_COMPANY_BUTTON_HELPTEXT :{BLACK}Dangos amcanion y cwmni STR_GOALS_TEXT :{ORANGE}{STRING} STR_GOALS_NONE :{ORANGE}- Dim - STR_GOALS_PROGRESS :{ORANGE}{STRING} @@ -3283,6 +3300,7 @@ STR_FINANCES_CAPTION :{WHITE}Cyllid { STR_FINANCES_YEAR :{WHITE}{NUM} ###length 3 +STR_FINANCES_OPERATING_EXPENSES_TITLE :{WHITE}Costau Gweithredol ###length 13 @@ -3704,6 +3722,7 @@ STR_REPLACE_MONORAIL_VEHICLES :Cerbydau Monore STR_REPLACE_MAGLEV_VEHICLES :Cerbydau Maglef +STR_REPLACE_REMOVE_WAGON :{BLACK}Tynnu wagenni: ({STRING}): {ORANGE}{STRING} STR_REPLACE_REMOVE_WAGON_HELP :{BLACK}Gwneud i awtoddisodli gadw hyd y trên yr un peth drwy dynnu wagenni (gan ddechrau yn y blaen), os byddai newid yr injan yn gwneud y trên yn hirach # Vehicle view @@ -3794,6 +3813,7 @@ STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED :{BLACK}Pwys: {L STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :{BLACK}Pwys: {LTBLUE}{WEIGHT_SHORT} {BLACK}Pŵer: {LTBLUE}{POWER}{BLACK} Cyflym. Max: {LTBLUE}{VELOCITY} {BLACK}Max. T.E.: {LTBLUE}{FORCE} STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR :{BLACK}Elw eleni: {LTBLUE}{CURRENCY_LONG} (llynedd: {CURRENCY_LONG}) +STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR_MIN_PERFORMANCE :{BLACK}Elw eleni: {LTBLUE}{CURRENCY_LONG} (Elw llynedd : {CURRENCY_LONG}) {BLACK}Perfformiad isafsymol: {LTBLUE}{POWER_TO_WEIGHT} STR_VEHICLE_INFO_RELIABILITY_BREAKDOWNS :{BLACK}Dibynadwyedd: {LTBLUE}{COMMA}% {BLACK}Toriadau ers gwasanaeth olaf: {LTBLUE}{COMMA} STR_VEHICLE_INFO_BUILT_VALUE :{LTBLUE}{ENGINE} {BLACK}Codi: {LTBLUE}{NUM}{BLACK} Pris: {LTBLUE}{CURRENCY_LONG} @@ -4140,7 +4160,7 @@ STR_AI_CONFIG_MOVE_DOWN_TOOLTIP :{BLACK}Symud yr STR_AI_CONFIG_GAMESCRIPT :{SILVER}Sgript Gêm STR_AI_CONFIG_AI :{SILVER}AIau -STR_AI_CONFIG_CHANGE_AI :AI +STR_AI_CONFIG_CHANGE_AI :{BLACK} Dewis AI STR_AI_CONFIG_CHANGE_GAMESCRIPT :Sgript Gêm STR_AI_CONFIG_CHANGE_TOOLTIP :{BLACK}Llwytho sgript arall STR_AI_CONFIG_CONFIGURE :{BLACK}Ffurfweddu @@ -4161,6 +4181,7 @@ STR_AI_LIST_ACCEPT_TOOLTIP :{BLACK}Dewis y STR_AI_LIST_CANCEL :{BLACK}Canslo STR_AI_LIST_CANCEL_TOOLTIP :{BLACK}Peidio newid y sgript +STR_SCREENSHOT_CAPTION :{WHITE}Creu ciplun # Script Parameters STR_AI_SETTINGS_CAPTION_AI :AI @@ -4421,6 +4442,7 @@ STR_ERROR_DEPOT_WRONG_DEPOT_TYPE :math depo anghy STR_ERROR_TRAIN_TOO_LONG_AFTER_REPLACEMENT :{WHITE}Aeth gormod o amser heibio i allu adnewyddu {VEHICLE} STR_ERROR_AUTOREPLACE_NOTHING_TO_DO :{WHITE}Ni weithredwyd unrhyw reolau awtogyfnewid/adnewyddu STR_ERROR_AUTOREPLACE_MONEY_LIMIT :(terfyn arian) +STR_ERROR_AUTOREPLACE_INCOMPATIBLE_CARGO :{WHITE}Nid yw'r cerbyd newydd yn gallu cario {STRING} # Rail construction errors STR_ERROR_IMPOSSIBLE_TRACK_COMBINATION :{WHITE}Cyfuniad trac amhosib @@ -4601,6 +4623,7 @@ STR_ERROR_TOO_FAR_FROM_PREVIOUS_DESTINATION :{WHITE}... rhy STR_ERROR_AIRCRAFT_NOT_ENOUGH_RANGE :{WHITE}... nid yw o fewn cyrraedd yr awyren # Extra messages which go on the third line of errors, explaining why orders failed +STR_ERROR_AIRPORT_NO_PLANES :{WHITE}Nid yw'r awyren yma'n gallu glanio yn yr hofrenfa yma # Timetable related errors STR_ERROR_CAN_T_TIMETABLE_VEHICLE :{WHITE}Methu amserlennu cerbyd... @@ -4743,7 +4766,7 @@ STR_SV_STNAME_SIDINGS :Cilffordd {STRI STR_SV_STNAME_BRANCH :Cangen {STRING} STR_SV_STNAME_UPPER :Blaenau {STRING} STR_SV_STNAME_LOWER :Dyffryn {STRING} -STR_SV_STNAME_HELIPORT :Hofrenyddborth {STRING} +STR_SV_STNAME_HELIPORT :Hofrenfa {STRING} STR_SV_STNAME_FOREST :Coedwig {STRING} STR_SV_STNAME_FALLBACK :{STRING} Gorsaf #{NUM} From 69d5b9d326dd6055f0af3c9f1adef474c236936a Mon Sep 17 00:00:00 2001 From: Rubidium Date: Tue, 27 Jun 2023 21:28:14 +0200 Subject: [PATCH 14/21] Cleanup: unused NO_THREADS #ifdefs --- src/os/unix/unix.cpp | 11 +++-------- src/thread.h | 2 -- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/os/unix/unix.cpp b/src/os/unix/unix.cpp index 9e99cbee57..8ca3db7692 100644 --- a/src/os/unix/unix.cpp +++ b/src/os/unix/unix.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #ifdef WITH_SDL2 #include @@ -47,10 +48,6 @@ #include #endif -#ifndef NO_THREADS -#include -#endif - #if defined(__APPLE__) # include "../macosx/macos.h" #endif @@ -258,11 +255,9 @@ void OSOpenBrowser(const char *url) #endif /* __APPLE__ */ void SetCurrentThreadName(const char *threadName) { -#if !defined(NO_THREADS) && defined(__GLIBC__) -#if __GLIBC_PREREQ(2, 12) +#if defined(__GLIBC__) if (threadName) pthread_setname_np(pthread_self(), threadName); -#endif /* __GLIBC_PREREQ(2, 12) */ -#endif /* !defined(NO_THREADS) && defined(__GLIBC__) */ +#endif /* defined(__GLIBC__) */ #if defined(__APPLE__) MacOSSetThreadName(threadName); #endif /* defined(__APPLE__) */ diff --git a/src/thread.h b/src/thread.h index 24f4f8e2aa..67140644c7 100644 --- a/src/thread.h +++ b/src/thread.h @@ -45,7 +45,6 @@ void SetCurrentThreadName(const char *name); template inline bool StartNewThread(std::thread *thr, const char *name, TFn&& _Fx, TArgs&&... _Ax) { -#ifndef NO_THREADS try { static std::mutex thread_startup_mutex; std::lock_guard lock(thread_startup_mutex); @@ -79,7 +78,6 @@ inline bool StartNewThread(std::thread *thr, const char *name, TFn&& _Fx, TArgs& /* Something went wrong, the system we are running on might not support threads. */ Debug(misc, 1, "Can't create thread '{}': {}", name, e.what()); } -#endif return false; } From fd380127f004ded84d0930ee392a6498b723bcd3 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Wed, 28 Jun 2023 22:20:19 +0200 Subject: [PATCH 15/21] Codechange: use SignalObjectAndWait since we do not support older than Windows XP anymore --- src/sound/win32_s.cpp | 3 +-- src/video/dedicated_v.cpp | 6 ++---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/sound/win32_s.cpp b/src/sound/win32_s.cpp index 87959e5860..f9fda5a349 100644 --- a/src/sound/win32_s.cpp +++ b/src/sound/win32_s.cpp @@ -98,8 +98,7 @@ void SoundDriver_Win32::Stop() /* Stop the sound thread. */ _waveout = nullptr; - SetEvent(_event); - WaitForSingleObject(_thread, INFINITE); + SignalObjectAndWait(_event, _thread, INFINITE, FALSE); /* Close the sound device. */ waveOutReset(waveout); diff --git a/src/video/dedicated_v.cpp b/src/video/dedicated_v.cpp index 4b492c7019..c17424874c 100644 --- a/src/video/dedicated_v.cpp +++ b/src/video/dedicated_v.cpp @@ -64,10 +64,8 @@ static void WINAPI CheckForConsoleInput() if (nb >= lengthof(_win_console_thread_buffer)) nb = lengthof(_win_console_thread_buffer) - 1; _win_console_thread_buffer[nb] = '\0'; - /* Signal input waiting that input is read and wait for it being handled - * SignalObjectAndWait() should be used here, but it's unsupported in Win98< */ - SetEvent(_hInputReady); - WaitForSingleObject(_hWaitForInputHandling, INFINITE); + /* Signal input waiting that input is read and wait for it being handled. */ + SignalObjectAndWait(_hInputReady, _hWaitForInputHandling, INFINITE, FALSE); } } From f333372dd19b97319e8ade72e0007fa5295f200c Mon Sep 17 00:00:00 2001 From: Rubidium Date: Wed, 28 Jun 2023 22:40:03 +0200 Subject: [PATCH 16/21] Codechange: let IConsoleCmdExec accept std::string --- src/console.cpp | 18 +++++++++--------- src/console_func.h | 2 +- src/network/network_admin.cpp | 2 +- src/network/network_server.cpp | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/console.cpp b/src/console.cpp index fa977469ed..da48ec3ad6 100644 --- a/src/console.cpp +++ b/src/console.cpp @@ -225,7 +225,7 @@ static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char break; case ';': // Cmd separator; execute previous and start new command - IConsoleCmdExec(alias_buffer.c_str(), recurse_count); + IConsoleCmdExec(alias_buffer, recurse_count); alias_buffer.clear(); @@ -283,15 +283,15 @@ static void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char } } - IConsoleCmdExec(alias_buffer.c_str(), recurse_count); + IConsoleCmdExec(alias_buffer, recurse_count); } /** * Execute a given command passed to us. First chop it up into * individual tokens (separated by spaces), then execute it if possible - * @param cmdstr string to be parsed and executed + * @param command_string string to be parsed and executed */ -void IConsoleCmdExec(const char *cmdstr, const uint recurse_count) +void IConsoleCmdExec(const std::string &command_string, const uint recurse_count) { const char *cmdptr; char *tokens[ICON_TOKEN_COUNT], tokenstream[ICON_MAX_STREAMSIZE]; @@ -300,16 +300,16 @@ void IConsoleCmdExec(const char *cmdstr, const uint recurse_count) bool longtoken = false; bool foundtoken = false; - if (cmdstr[0] == '#') return; // comments + if (command_string[0] == '#') return; // comments - for (cmdptr = cmdstr; *cmdptr != '\0'; cmdptr++) { + for (cmdptr = command_string.c_str(); *cmdptr != '\0'; cmdptr++) { if (!IsValidChar(*cmdptr, CS_ALPHANUMERAL)) { - IConsolePrint(CC_ERROR, "Command '{}' contains malformed characters.", cmdstr); + IConsolePrint(CC_ERROR, "Command '{}' contains malformed characters.", command_string); return; } } - Debug(console, 4, "Executing cmdline: '{}'", cmdstr); + Debug(console, 4, "Executing cmdline: '{}'", command_string); memset(&tokens, 0, sizeof(tokens)); memset(&tokenstream, 0, sizeof(tokenstream)); @@ -317,7 +317,7 @@ void IConsoleCmdExec(const char *cmdstr, const uint recurse_count) /* 1. Split up commandline into tokens, separated by spaces, commands * enclosed in "" are taken as one token. We can only go as far as the amount * of characters in our stream or the max amount of tokens we can handle */ - for (cmdptr = cmdstr, t_index = 0, tstream_i = 0; *cmdptr != '\0'; cmdptr++) { + for (cmdptr = command_string.c_str(), t_index = 0, tstream_i = 0; *cmdptr != '\0'; cmdptr++) { if (tstream_i >= lengthof(tokenstream)) { IConsolePrint(CC_ERROR, "Command line too long."); return; diff --git a/src/console_func.h b/src/console_func.h index 484a71573c..09f1e19ebb 100644 --- a/src/console_func.h +++ b/src/console_func.h @@ -47,7 +47,7 @@ static inline void IConsolePrint(TextColour colour_code, const T &format, A firs } /* Parser */ -void IConsoleCmdExec(const char *cmdstr, const uint recurse_count = 0); +void IConsoleCmdExec(const std::string &command_string, const uint recurse_count = 0); bool IsValidConsoleColour(TextColour c); diff --git a/src/network/network_admin.cpp b/src/network/network_admin.cpp index 7e9433efdf..a016ad4430 100644 --- a/src/network/network_admin.cpp +++ b/src/network/network_admin.cpp @@ -501,7 +501,7 @@ NetworkRecvStatus ServerNetworkAdminSocketHandler::Receive_ADMIN_RCON(Packet *p) Debug(net, 3, "[admin] Rcon command from '{}' ({}): {}", this->admin_name, this->admin_version, command); _redirect_console_to_admin = this->index; - IConsoleCmdExec(command.c_str()); + IConsoleCmdExec(command); _redirect_console_to_admin = INVALID_ADMIN_ID; return this->SendRconEnd(command); } diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 79b780f06c..86c908cf89 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -1402,7 +1402,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::Receive_CLIENT_RCON(Packet *p) Debug(net, 3, "[rcon] Client-id {} executed: {}", this->client_id, command); _redirect_console_to_client = this->client_id; - IConsoleCmdExec(command.c_str()); + IConsoleCmdExec(command); _redirect_console_to_client = INVALID_CLIENT_ID; return NETWORK_RECV_STATUS_OKAY; } From 3f18a8863ad776d8936a2ea0a37ecd5bfaa7bd0b Mon Sep 17 00:00:00 2001 From: Rubidium Date: Wed, 28 Jun 2023 22:31:38 +0200 Subject: [PATCH 17/21] Codechange: use std::getline to read strings from stdin --- src/video/dedicated_v.cpp | 31 ++++++++++--------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/src/video/dedicated_v.cpp b/src/video/dedicated_v.cpp index c17424874c..9b17c060bf 100644 --- a/src/video/dedicated_v.cpp +++ b/src/video/dedicated_v.cpp @@ -23,6 +23,7 @@ #include "../saveload/saveload.h" #include "../thread.h" #include "../window_func.h" +#include #include "dedicated_v.h" #if defined(UNIX) @@ -50,19 +51,15 @@ static void DedicatedSignalHandler(int sig) static HANDLE _hInputReady, _hWaitForInputHandling; static HANDLE _hThread; // Thread to close -static char _win_console_thread_buffer[200]; +static std::string _win_console_thread_buffer; /* Windows Console thread. Just loop and signal when input has been received */ static void WINAPI CheckForConsoleInput() { SetCurrentThreadName("ottd:win-console"); - DWORD nb; - HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); for (;;) { - ReadFile(hStdin, _win_console_thread_buffer, lengthof(_win_console_thread_buffer), &nb, nullptr); - if (nb >= lengthof(_win_console_thread_buffer)) nb = lengthof(_win_console_thread_buffer) - 1; - _win_console_thread_buffer[nb] = '\0'; + std::getline(std::cin, _win_console_thread_buffer); /* Signal input waiting that input is read and wait for it being handled. */ SignalObjectAndWait(_hInputReady, _hWaitForInputHandling, INFINITE, FALSE); @@ -174,31 +171,23 @@ static bool InputWaiting() static void DedicatedHandleKeyInput() { - static char input_line[1024] = ""; - if (!InputWaiting()) return; if (_exit_game) return; + std::string input_line; #if defined(UNIX) - if (fgets(input_line, lengthof(input_line), stdin) == nullptr) return; + if (!std::getline(std::cin, input_line)) return; #else /* Handle console input, and signal console thread, it can accept input again */ - static_assert(lengthof(_win_console_thread_buffer) <= lengthof(input_line)); - strecpy(input_line, _win_console_thread_buffer, lastof(input_line)); + std::swap(input_line, _win_console_thread_buffer); SetEvent(_hWaitForInputHandling); #endif - /* Remove trailing \r or \n */ - for (char *c = input_line; *c != '\0'; c++) { - if (*c == '\n' || *c == '\r' || c == lastof(input_line)) { - *c = '\0'; - break; - } - } - StrMakeValidInPlace(input_line, lastof(input_line)); - - IConsoleCmdExec(input_line); // execute command + /* Remove any trailing \r or \n, and ensure the string is valid. */ + auto p = input_line.find_last_not_of("\r\n"); + if (p != std::string::npos) p++; + IConsoleCmdExec(StrMakeValid(input_line.substr(0, p))); } void VideoDriver_Dedicated::MainLoop() From 0ea3e338ab66b93938e62f9d3a76609a7dcc2619 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Thu, 29 Jun 2023 16:27:17 +0200 Subject: [PATCH 18/21] Codechange: replace buffer+strecpy with std::string --- src/network/network_content.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp index c79bb1c012..e30bbbff98 100644 --- a/src/network/network_content.cpp +++ b/src/network/network_content.cpp @@ -699,19 +699,19 @@ void ClientNetworkContentSocketHandler::OnReceiveData(const char *data, size_t l check_not_null(p); p++; // Start after the '/' - char tmp[MAX_PATH]; - if (strecpy(tmp, p, lastof(tmp)) == lastof(tmp)) { - this->OnFailure(); - return; - } + std::string filename = p; /* Remove the extension from the string. */ for (uint i = 0; i < 2; i++) { - p = strrchr(tmp, '.'); - check_and_terminate(p); + auto pos = filename.find_last_of('.'); + if (pos == std::string::npos) { + this->OnFailure(); + return; + } + filename.erase(pos); } /* Copy the string, without extension, to the filename. */ - this->curInfo->filename = tmp; + this->curInfo->filename = std::move(filename); /* Request the next file. */ if (!this->BeforeDownload()) { From d5c75bd655d80565367f5bf00fc8260a5d67af78 Mon Sep 17 00:00:00 2001 From: Rubidium Date: Fri, 30 Jun 2023 18:15:32 +0200 Subject: [PATCH 19/21] Codechange: use std::string instead of a temporary buffer for iconv calls --- src/os/unix/unix.cpp | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/os/unix/unix.cpp b/src/os/unix/unix.cpp index 8ca3db7692..f641bedcfd 100644 --- a/src/os/unix/unix.cpp +++ b/src/os/unix/unix.cpp @@ -124,29 +124,30 @@ static const char *GetLocalCode() * Convert between locales, which from and which to is set in the calling * functions OTTD2FS() and FS2OTTD(). */ -static const char *convert_tofrom_fs(iconv_t convd, const char *name, char *outbuf, size_t outlen) +static std::string convert_tofrom_fs(iconv_t convd, const std::string &name) { /* There are different implementations of iconv. The older ones, * e.g. SUSv2, pass a const pointer, whereas the newer ones, e.g. * IEEE 1003.1 (2004), pass a non-const pointer. */ #ifdef HAVE_NON_CONST_ICONV - char *inbuf = const_cast(name); + char *inbuf = const_cast(name.data()); #else - const char *inbuf = name; + const char *inbuf = name.data(); #endif - size_t inlen = strlen(name); - char *buf = outbuf; - - strecpy(outbuf, name, outbuf + outlen); + /* If the output is UTF-32, then 1 ASCII character becomes 4 bytes. */ + size_t inlen = name.size(); + std::string buf(inlen * 4, '\0'); + size_t outlen = buf.size(); + char *outbuf = buf.data(); iconv(convd, nullptr, nullptr, nullptr, nullptr); if (iconv(convd, &inbuf, &inlen, &outbuf, &outlen) == (size_t)(-1)) { Debug(misc, 0, "[iconv] error converting '{}'. Errno {}", name, errno); + return name; } - *outbuf = '\0'; - /* FIX: invalid characters will abort conversion, but they shouldn't occur? */ + buf.resize(outbuf - buf.data()); return buf; } @@ -158,8 +159,6 @@ static const char *convert_tofrom_fs(iconv_t convd, const char *name, char *outb std::string OTTD2FS(const std::string &name) { static iconv_t convd = (iconv_t)(-1); - char buf[1024] = {}; - if (convd == (iconv_t)(-1)) { const char *env = GetLocalCode(); convd = iconv_open(env, INTERNALCODE); @@ -169,7 +168,7 @@ std::string OTTD2FS(const std::string &name) } } - return convert_tofrom_fs(convd, name.c_str(), buf, lengthof(buf)); + return convert_tofrom_fs(convd, name); } /** @@ -180,8 +179,6 @@ std::string OTTD2FS(const std::string &name) std::string FS2OTTD(const std::string &name) { static iconv_t convd = (iconv_t)(-1); - char buf[1024] = {}; - if (convd == (iconv_t)(-1)) { const char *env = GetLocalCode(); convd = iconv_open(INTERNALCODE, env); @@ -191,7 +188,7 @@ std::string FS2OTTD(const std::string &name) } } - return convert_tofrom_fs(convd, name.c_str(), buf, lengthof(buf)); + return convert_tofrom_fs(convd, name); } #endif /* WITH_ICONV */ From 082c47a4f9579164804c6473fc282173ed9e18dd Mon Sep 17 00:00:00 2001 From: translators Date: Fri, 30 Jun 2023 18:40:38 +0000 Subject: [PATCH 20/21] Update: Translations from eints dutch: 1 change by Afoklala --- src/lang/dutch.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lang/dutch.txt b/src/lang/dutch.txt index f8cab25a52..610e421fa3 100644 --- a/src/lang/dutch.txt +++ b/src/lang/dutch.txt @@ -951,6 +951,7 @@ STR_GAME_OPTIONS_VOLUME_100 :100% STR_GAME_OPTIONS_CURRENCY_UNITS_FRAME :{BLACK}Valuta STR_GAME_OPTIONS_CURRENCY_UNITS_DROPDOWN_TOOLTIP :{BLACK}Valuta kiezen +STR_GAME_OPTIONS_CURRENCY_CODE :{STRING} ({STRING}) ###length 42 STR_GAME_OPTIONS_CURRENCY_GBP :Britse Pond From c3fbe7bea809777bca95eee09877a0a714a0ed84 Mon Sep 17 00:00:00 2001 From: PeterN Date: Fri, 30 Jun 2023 21:11:09 +0100 Subject: [PATCH 21/21] Cleanup: Use FS enum instead of magic numbers. (#11088) --- src/strings.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/strings.cpp b/src/strings.cpp index 43748f0109..e3abf74d5d 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -2111,10 +2111,10 @@ bool MissingGlyphSearcher::FindMissingGlyphs() std::string size_name; switch (size) { - case 0: size_name = "medium"; break; - case 1: size_name = "small"; break; - case 2: size_name = "large"; break; - case 3: size_name = "mono"; break; + case FS_NORMAL: size_name = "medium"; break; + case FS_SMALL: size_name = "small"; break; + case FS_LARGE: size_name = "large"; break; + case FS_MONO: size_name = "mono"; break; default: NOT_REACHED(); }