44#include "table/strings.h"
46#include "3rdparty/fmt/std.h"
72 throw std::out_of_range(
"Trying to read invalid string parameter");
76 if (param.type != 0 && param.type != this->next_type) {
78 throw std::out_of_range(
"Trying to read string parameter with wrong type");
112 void operator()(
const std::monostate &) {}
114 void operator()(
const uint64_t &arg)
120 void operator()(
const std::string &value)
130 this->builder += value;
135 for (
const auto ¶m : params) {
136 builder.
PutUtf8(SCC_RECORD_SEPARATOR);
137 std::visit(v, param.data);
152 if (this->empty())
return {};
154 std::vector<StringParameter> params;
172 params.emplace_back(std::monostate{});
177 char32_t parameter_type = record.
ReadUtf8();
178 switch (parameter_type) {
182 params.emplace_back(value);
193 params.emplace_back(std::monostate{});
198 if (param >= std::size(params))
return {};
199 params[param] = data;
209 return GetString(STR_JUST_RAW_STRING, this->
string);
221 uint64_t val = count > 1 ? front : next;
222 for (; count > 1; count--) {
223 val = 10 * val + next;
239 while (max_value >= 10) {
261static void FormatString(
StringBuilder &builder, std::string_view str, std::span<StringParameter> params, uint case_index = 0,
bool game_script =
false,
bool dry_run =
false)
264 FormatString(builder, str, tmp_params, case_index, game_script, dry_run);
275 delete[]
reinterpret_cast<char *
>(langpack);
280 std::unique_ptr<LanguagePack, LanguagePackDeleter> langpack;
282 std::vector<std::string_view> strings;
301 return _langpack.list_separator;
310 return _langpack.ellipsis;
313std::string_view GetStringPtr(
StringID string)
318 case TEXT_TAB_OLD_NEWGRF: NOT_REACHED();
322 if (offset < _langpack.strings.size())
return _langpack.strings[offset];
323 return "(undefined string)";
351 }
catch (
const std::runtime_error &e) {
352 Debug(misc, 0,
"GetStringWithArgs: {}", e.what());
353 builder +=
"(invalid string parameter)";
359 case TEXT_TAB_SPECIAL:
362 if (GetSpecialNameString(builder,
string, args))
return;
363 }
catch (
const std::runtime_error &e) {
364 Debug(misc, 0,
"GetStringWithArgs: {}", e.what());
365 builder +=
"(invalid string parameter)";
371 case TEXT_TAB_OLD_CUSTOM:
374 FatalError(
"Incorrect conversion of custom name string.");
383 case TEXT_TAB_OLD_NEWGRF:
395 if (index >= _langpack.langtab_num[tab]) {
399 FatalError(
"String 0x{:X} is invalid. You are probably using an old version of the .lng file.\n",
string);
402 FormatString(builder, GetStringPtr(
string), args, case_index);
440void AppendStringWithArgsInPlace(std::string &result,
StringID string, std::span<StringParameter> params)
469static std::string_view GetDecimalSeparator()
471 std::string_view decimal_separator =
_settings_game.locale.digit_decimal_separator;
472 if (decimal_separator.empty()) decimal_separator = _langpack.langpack->digit_decimal_separator;
473 return decimal_separator;
484 static const int max_digits = 20;
485 uint64_t divisor = 10000000000000000000ULL;
486 int thousands_offset = (max_digits - 1) % 3;
493 uint64_t num = number;
495 for (
int i = 0; i < max_digits; i++) {
497 if (num >= divisor) {
498 quot = num / divisor;
501 if ((tot |= quot) || i == max_digits - 1) {
503 if ((i % 3) == thousands_offset && i < max_digits - 1) builder += separator;
510static void FormatCommaNumber(
StringBuilder &builder, int64_t number)
512 std::string_view separator =
_settings_game.locale.digit_group_separator;
513 if (separator.empty()) separator = _langpack.langpack->digit_group_separator;
517static void FormatNoCommaNumber(
StringBuilder &builder, int64_t number)
522static void FormatZerofillNumber(
StringBuilder &builder, int64_t number,
int count)
524 fmt::format_to(builder.
back_inserter(),
"{:0{}d}", number, count);
527static void FormatHexNumber(
StringBuilder &builder, uint64_t number)
542 static const std::string_view iec_prefixes[] = {
"",
"Ki",
"Mi",
"Gi",
"Ti",
"Pi",
"Ei"};
544 while (number >= 1024 * 1024) {
552 }
else if (number < 1024 * 10) {
553 fmt::format_to(builder.
back_inserter(),
"{}{}{:02}", number / 1024, GetDecimalSeparator(), (number % 1024) * 100 / 1024);
554 }
else if (number < 1024 * 100) {
555 fmt::format_to(builder.
back_inserter(),
"{}{}{:01}", number / 1024, GetDecimalSeparator(), (number % 1024) * 10 / 1024);
557 assert(number < 1024 * 1024);
558 fmt::format_to(builder.
back_inserter(),
"{}", number / 1024);
561 assert(
id <
lengthof(iec_prefixes));
569 auto tmp_params =
MakeParameters(STR_DAY_NUMBER_1ST + ymd.day - 1, STR_MONTH_ABBREV_JAN + ymd.month, ymd.year);
570 FormatString(builder, GetStringPtr(STR_FORMAT_DATE_LONG), tmp_params, case_index);
577 auto tmp_params =
MakeParameters(STR_MONTH_JAN + ymd.month, ymd.year);
578 FormatString(builder, GetStringPtr(STR_FORMAT_DATE_SHORT), tmp_params, case_index);
586 auto tmp_params =
MakeParameters(ymd.day, 2, ymd.month + 1, 2, ymd.year);
594 bool negative = number < 0;
596 number *= spec->
rate;
600 builder.
PutUtf8(SCC_PUSH_COLOUR);
615 if (number >= Money(1'000'000'000'000'000) - 500'000'000) {
616 number = (number + Money(500'000'000'000)) / Money(1'000'000'000'000);
617 number_str = STR_CURRENCY_SHORT_TERA;
618 }
else if (number >= Money(1'000'000'000'000) - 500'000) {
619 number = (number + 500'000'000) / 1'000'000'000;
620 number_str = STR_CURRENCY_SHORT_GIGA;
621 }
else if (number >= 1'000'000'000 - 500) {
622 number = (number + 500'000) / 1'000'000;
623 number_str = STR_CURRENCY_SHORT_MEGA;
624 }
else if (number >= 1'000'000) {
625 number = (number + 500) / 1'000;
626 number_str = STR_CURRENCY_SHORT_KILO;
630 std::string_view separator =
_settings_game.locale.digit_group_separator_currency;
632 if (separator.empty()) separator = _langpack.langpack->digit_group_separator_currency;
634 if (number_str != STR_NULL) {
642 builder.
PutUtf8(SCC_POP_COLOUR);
655 uint64_t n =
abs(count);
657 switch (plural_form) {
666 return n != 1 ? 1 : 0;
678 return n > 1 ? 1 : 0;
685 return n % 10 == 1 && n % 100 != 11 ? 0 : n != 0 ? 1 : 2;
691 return n == 1 ? 0 : n == 2 ? 1 : n < 7 ? 2 : n < 11 ? 3 : 4;
697 return n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
703 return n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
709 return n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
715 return n % 100 == 1 ? 0 : n % 100 == 2 ? 1 : n % 100 == 3 || n % 100 == 4 ? 2 : 3;
721 return n % 10 == 1 && n % 100 != 11 ? 0 : 1;
727 return n == 1 ? 0 : n >= 2 && n <= 4 ? 1 : 2;
758 return (n == 1 ? 0 : n == 0 || (n % 100 > 1 && n % 100 < 11) ? 1 : (n % 100 > 10 && n % 100 < 20) ? 2 : 3);
763 return ((n == 1 || n == 11) ? 0 : (n == 2 || n == 12) ? 1 : ((n > 2 && n < 11) || (n > 12 && n < 20)) ? 2 : 3);
769 return n == 1 ? 0 : (n == 0 || (n % 100 > 0 && n % 100 < 20)) ? 1 : 2;
777 for (uint i = 0; i != n; i++) {
787 size_t form_pre = 0, form_len = 0, form_post = 0;
788 for (uint i = 0; i != n; i++) {
792 }
else if (i > form) {
799 consumer.
Skip(form_pre);
800 builder += consumer.
Read(form_len);
801 consumer.
Skip(form_post);
814 int64_t
ToDisplay(int64_t input,
bool round =
true)
const
817 ? (int64_t)std::round(input * this->factor)
818 : (int64_t)(input * this->factor);
828 int64_t
FromDisplay(int64_t input,
bool round =
true, int64_t divider = 1)
const
831 ? (int64_t)std::round(input / this->factor / divider)
832 : (int64_t)(input / this->factor / divider);
853 { { 1.0 }, STR_UNITS_VELOCITY_IMPERIAL, 0 },
854 { { 1.609344 }, STR_UNITS_VELOCITY_METRIC, 0 },
855 { { 0.44704 }, STR_UNITS_VELOCITY_SI, 0 },
856 { { 0.578125 }, STR_UNITS_VELOCITY_GAMEUNITS_DAY, 1 },
857 { { 0.868976 }, STR_UNITS_VELOCITY_KNOTS, 0 },
862 { { 1.0 }, STR_UNITS_VELOCITY_IMPERIAL, 0 },
863 { { 1.609344 }, STR_UNITS_VELOCITY_METRIC, 0 },
864 { { 0.44704 }, STR_UNITS_VELOCITY_SI, 0 },
865 { { 0.289352 }, STR_UNITS_VELOCITY_GAMEUNITS_SEC, 1 },
866 { { 0.868976 }, STR_UNITS_VELOCITY_KNOTS, 0 },
871 { { 1.0 }, STR_UNITS_POWER_IMPERIAL, 0 },
872 { { 1.01387 }, STR_UNITS_POWER_METRIC, 0 },
873 { { 0.745699 }, STR_UNITS_POWER_SI, 0 },
878 { { 0.907185 }, STR_UNITS_POWER_IMPERIAL_TO_WEIGHT_IMPERIAL, 1 },
879 { { 1.0 }, STR_UNITS_POWER_IMPERIAL_TO_WEIGHT_METRIC, 1 },
880 { { 1.0 }, STR_UNITS_POWER_IMPERIAL_TO_WEIGHT_SI, 1 },
881 { { 0.919768 }, STR_UNITS_POWER_METRIC_TO_WEIGHT_IMPERIAL, 1 },
882 { { 1.01387 }, STR_UNITS_POWER_METRIC_TO_WEIGHT_METRIC, 1 },
883 { { 1.01387 }, STR_UNITS_POWER_METRIC_TO_WEIGHT_SI, 1 },
884 { { 0.676487 }, STR_UNITS_POWER_SI_TO_WEIGHT_IMPERIAL, 1 },
885 { { 0.745699 }, STR_UNITS_POWER_SI_TO_WEIGHT_METRIC, 1 },
886 { { 0.745699 }, STR_UNITS_POWER_SI_TO_WEIGHT_SI, 1 },
891 { { 1.102311 }, STR_UNITS_WEIGHT_SHORT_IMPERIAL, STR_UNITS_WEIGHT_LONG_IMPERIAL, 0 },
892 { { 1.0 }, STR_UNITS_WEIGHT_SHORT_METRIC, STR_UNITS_WEIGHT_LONG_METRIC, 0 },
893 { { 1000.0 }, STR_UNITS_WEIGHT_SHORT_SI, STR_UNITS_WEIGHT_LONG_SI, 0 },
898 { { 264.172 }, STR_UNITS_VOLUME_SHORT_IMPERIAL, STR_UNITS_VOLUME_LONG_IMPERIAL, 0 },
899 { { 1000.0 }, STR_UNITS_VOLUME_SHORT_METRIC, STR_UNITS_VOLUME_LONG_METRIC, 0 },
900 { { 1.0 }, STR_UNITS_VOLUME_SHORT_SI, STR_UNITS_VOLUME_LONG_SI, 0 },
905 { { 0.224809 }, STR_UNITS_FORCE_IMPERIAL, 0 },
906 { { 0.101972 }, STR_UNITS_FORCE_METRIC, 0 },
907 { { 0.001 }, STR_UNITS_FORCE_SI, 0 },
912 { { 3.0 }, STR_UNITS_HEIGHT_IMPERIAL, 0 },
913 { { 1.0 }, STR_UNITS_HEIGHT_METRIC, 0 },
914 { { 1.0 }, STR_UNITS_HEIGHT_SI, 0 },
915 { { .02 }, STR_UNITS_HEIGHT_GAMEUNITS,0 },
920 { { 1 }, STR_UNITS_DAYS, 0 },
921 { { 2 }, STR_UNITS_SECONDS, 0 },
926 { { 1 }, STR_UNITS_MONTHS, 0 },
927 { { 1 }, STR_UNITS_MINUTES, 0 },
932 { { 1 }, STR_UNITS_YEARS, 0 },
933 { { 1 }, STR_UNITS_PERIODS, 0 },
938 { { 1 }, STR_UNITS_YEARS, 0 },
939 { { 12 }, STR_UNITS_MINUTES, 0 },
1014 std::vector<StringParameter> sub_args;
1019 builder +=
"(invalid SCC_ENCODED)";
1024 builder +=
"(invalid StringID)";
1034 sub_args.emplace_back(std::monostate{});
1039 char32_t parameter_type = record.
ReadUtf8();
1040 switch (parameter_type) {
1044 builder +=
"(invalid sub-StringID)";
1049 sub_args.emplace_back(param);
1056 sub_args.emplace_back(param);
1067 sub_args.emplace_back(std::monostate{});
1084 for (
char32_t ch :
Utf8View(buffer)) {
1085 if (ch == SCC_PUSH_COLOUR) {
1087 }
else if (ch == SCC_POP_COLOUR) {
1089 if (safety < 0)
return false;
1090 }
else if ((ch >= SCC_BLUE && ch <= SCC_BLACK) || ch == SCC_COLOUR) {
1091 if (safety == 0)
return false;
1108 size_t orig_first_param_offset = args.
GetOffset();
1109 bool emit_automatic_push_pop =
false;
1122 FormatString(dry_run_builder, str_arg, args, orig_case_index, game_script,
true);
1125 args.
SetOffset(orig_first_param_offset);
1127 uint next_substr_case_index = 0;
1128 struct StrStackItem {
1130 size_t first_param_offset;
1133 StrStackItem(std::string_view view,
size_t first_param_offset, uint case_index)
1134 : consumer(view), first_param_offset(first_param_offset), case_index(case_index)
1137 std::stack<StrStackItem, std::vector<StrStackItem>> str_stack;
1138 str_stack.emplace(str_arg, orig_first_param_offset, orig_case_index);
1140 if (emit_automatic_push_pop) builder.
PutUtf8(SCC_PUSH_COLOUR);
1144 while (!str_stack.empty() && !str_stack.top().consumer.AnyBytesLeft()) {
1147 if (str_stack.empty())
break;
1149 const size_t ref_param_offset = str_stack.top().first_param_offset;
1150 const uint case_index = str_stack.top().case_index;
1155 builder +=
"(unexpected NUL)";
1162 if (b == 0)
continue;
1165 if (b < SCC_CONTROL_START || b > SCC_CONTROL_END) {
1170 args.SetTypeOfNextParameter(b);
1179 std::string_view ptr = GetStringPtr(substr);
1180 str_stack.emplace(ptr, args.
GetOffset(), next_substr_case_index);
1181 next_substr_case_index = 0;
1187 std::string_view ptr = GetStringPtr(substr);
1188 str_stack.emplace(ptr, args.
GetOffset(), next_substr_case_index);
1189 next_substr_case_index = 0;
1193 case SCC_GENDER_LIST: {
1195 size_t offset = ref_param_offset + consumer.
ReadUint8();
1199 builder +=
"(invalid GENDER parameter)";
1221 if (gender_consumer.
ReadUtf8If(SCC_GENDER_INDEX)) {
1225 ParseStringChoice(consumer, gender, builder);
1231 case SCC_GENDER_INDEX: {
1234 builder.
PutUtf8(SCC_GENDER_INDEX);
1240 case SCC_PLURAL_LIST: {
1241 uint8_t plural_form = consumer.
ReadUint8();
1242 size_t offset = ref_param_offset + consumer.
ReadUint8();
1243 const uint64_t *v =
nullptr;
1246 v = std::get_if<uint64_t>(&args.GetParam(offset));
1249 ParseStringChoice(consumer,
DeterminePluralForm(
static_cast<int64_t
>(*v), plural_form), builder);
1251 SkipStringChoice(consumer);
1252 builder +=
"(invalid PLURAL parameter)";
1257 case SCC_ARG_INDEX: {
1262 case SCC_SET_CASE: {
1265 next_substr_case_index = consumer.
ReadUint8();
1269 case SCC_SWITCH_CASE: {
1273 std::optional<std::string_view> found;
1274 for (; num > 0; --num) {
1277 auto case_str = consumer.
Read(len);
1278 if (index == case_index) {
1284 auto default_str = consumer.
Read(default_len);
1285 if (!found.has_value()) found = default_str;
1286 str_stack.emplace(*found, ref_param_offset, case_index);
1291 builder += _openttd_revision;
1294 case SCC_RAW_STRING_POINTER:
1303 GetStringWithArgs(builder, string_id, tmp_params, next_substr_case_index, game_script);
1304 next_substr_case_index = 0;
1318 uint size = b - SCC_STRING1 + 1;
1320 builder +=
"(consumed too many parameters)";
1323 GetStringWithArgs(builder, string_id, sub_args, next_substr_case_index, game_script);
1326 next_substr_case_index = 0;
1338 FormatCommaNumber(builder, number);
1343 int64_t fractional = number % divisor;
1345 FormatCommaNumber(builder, number);
1346 fmt::format_to(builder.
back_inserter(),
"{}{:0{}d}", GetDecimalSeparator(), fractional, digits);
1354 case SCC_ZEROFILL_NUM: {
1368 case SCC_CARGO_TINY: {
1376 builder +=
"(invalid cargo type)";
1393 FormatCommaNumber(builder, amount);
1397 case SCC_CARGO_SHORT: {
1405 builder +=
"(invalid cargo type)";
1410 switch (cargo_str) {
1414 auto tmp_params =
MakeParameters(x.c.ToDisplay(amount), x.decimal_places);
1422 auto tmp_params =
MakeParameters(x.c.ToDisplay(amount), x.decimal_places);
1436 case SCC_CARGO_LONG: {
1446 builder +=
"(invalid cargo type)";
1451 case SCC_CARGO_LIST: {
1457 if (!cmask.
Test(cs->Index()))
continue;
1463 builder += list_separator;
1466 GetStringWithArgs(builder, cs->name, args, next_substr_case_index, game_script);
1470 if (first)
GetStringWithArgs(builder, STR_JUST_NOTHING, args, next_substr_case_index, game_script);
1472 next_substr_case_index = 0;
1476 case SCC_CURRENCY_SHORT:
1480 case SCC_CURRENCY_LONG:
1488 case SCC_DATE_SHORT:
1490 next_substr_case_index = 0;
1495 next_substr_case_index = 0;
1526 case SCC_POWER_TO_WEIGHT: {
1535 case SCC_VELOCITY: {
1545 case SCC_VOLUME_SHORT: {
1553 case SCC_VOLUME_LONG: {
1561 case SCC_WEIGHT_SHORT: {
1569 case SCC_WEIGHT_LONG: {
1577 case SCC_UNITS_DAYS_OR_SECONDS: {
1585 case SCC_UNITS_MONTHS_OR_MINUTES: {
1593 case SCC_UNITS_YEARS_OR_PERIODS: {
1601 case SCC_UNITS_YEARS_OR_MINUTES: {
1609 case SCC_COMPANY_NAME: {
1611 if (c ==
nullptr)
break;
1613 if (!c->
name.empty()) {
1623 case SCC_COMPANY_NUM: {
1634 case SCC_DEPOT_NAME: {
1643 if (!d->name.empty()) {
1653 case SCC_ENGINE_NAME: {
1656 if (e ==
nullptr)
break;
1658 if (!e->name.empty() && e->IsEnabled()) {
1665 std::array<int32_t, 16> regs100;
1668 if (callback == 0x40F) {
1669 const GRFFile *grffile = e->GetGRF();
1670 assert(grffile !=
nullptr);
1674 }
else if (callback < 0x400) {
1675 const GRFFile *grffile = e->GetGRF();
1676 assert(grffile !=
nullptr);
1687 case SCC_GROUP_NAME: {
1689 if (g ==
nullptr)
break;
1691 if (!g->
name.empty()) {
1701 case SCC_INDUSTRY_NAME: {
1703 if (i ==
nullptr)
break;
1705 static bool use_cache =
true;
1710 }
else if (use_cache) {
1712 builder += i->GetCachedName();
1716 FormatString(builder, GetStringPtr(STR_FORMAT_INDUSTRY_NAME), tmp_params, next_substr_case_index);
1718 next_substr_case_index = 0;
1722 case SCC_PRESIDENT_NAME: {
1724 if (c ==
nullptr)
break;
1736 case SCC_STATION_NAME: {
1740 if (st ==
nullptr) {
1748 static bool use_cache =
true;
1751 builder += st->GetCachedName();
1752 }
else if (!st->name.empty()) {
1756 StringID string_id = st->string_id;
1757 if (st->indtype != IT_INVALID) {
1769 auto tmp_params =
MakeParameters(STR_TOWN_NAME, st->town->index, st->index);
1775 case SCC_TOWN_NAME: {
1777 if (t ==
nullptr)
break;
1779 static bool use_cache =
true;
1782 builder += t->GetCachedName();
1783 }
else if (!t->
name.empty()) {
1787 GetTownName(builder, t);
1792 case SCC_WAYPOINT_NAME: {
1794 if (wp ==
nullptr)
break;
1796 if (!wp->
name.empty()) {
1801 StringID string_id = ((wp->
string_id == STR_SV_STNAME_BUOY) ? STR_FORMAT_BUOY_NAME : STR_FORMAT_WAYPOINT_NAME);
1802 if (wp->
town_cn != 0) string_id++;
1808 case SCC_VEHICLE_NAME: {
1810 if (v ==
nullptr)
break;
1812 if (!v->
name.empty()) {
1824 default: string_id = STR_INVALID_VEHICLE;
break;
1836 case SCC_SIGN_NAME: {
1838 if (si ==
nullptr)
break;
1840 if (!si->name.empty()) {
1849 case SCC_STATION_FEATURES: {
1864 }
catch (std::out_of_range &e) {
1865 Debug(misc, 0,
"FormatString: {}", e.what());
1866 builder +=
"(invalid parameter)";
1870 if (emit_automatic_push_pop) builder.
PutUtf8(SCC_POP_COLOUR);
1883static const std::string_view _silly_company_names[] = {
1885 "Tiny Transport Ltd.",
1887 "Comfy-Coach & Co.",
1888 "Crush & Bump Ltd.",
1889 "Broken & Late Ltd.",
1891 "Supersonic Travel",
1893 "Lightning International",
1894 "Pannik & Loozit Ltd.",
1895 "Inter-City Transport",
1896 "Getout & Pushit Ltd."
1899static const std::string_view _surname_list[] = {
1931static const std::string_view _silly_surname_list[] = {
1946static const char _initial_name_letters[] = {
1947 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
1948 'K',
'L',
'M',
'N',
'P',
'R',
'S',
'T',
'W',
1951static std::span<const std::string_view> GetSurnameOptions()
1954 return _surname_list;
1964 auto surname_options = GetSurnameOptions();
1965 return surname_options[surname_options.size() *
GB(seed, 16, 8) >> 8];
1968static void GenAndCoName(
StringBuilder &builder, uint32_t seed)
1971 builder +=
" & Co.";
1974static void GenPresidentName(
StringBuilder &builder, uint32_t seed)
1976 builder.
PutChar(_initial_name_letters[std::size(_initial_name_letters) *
GB(seed, 0, 8) >> 8]);
1980 size_t index = (std::size(_initial_name_letters) + 35) *
GB(seed, 8, 8) >> 8;
1981 if (index < std::size(_initial_name_letters)) {
1982 builder.
PutChar(_initial_name_letters[index]);
1993 builder += _silly_company_names[std::min<size_t>(args.
GetNextParameter<uint16_t>(), std::size(_silly_company_names) - 1)];
2008 builder +=
" Transport";
2022 this->
version == TO_LE32(LANGUAGE_PACK_VERSION) &&
2043 return 4 * this->
missing < LANGUAGE_TOTAL_STRINGS;
2054 size_t total_len = 0;
2056 if (!lang_pack)
return false;
2059 const char *end = (
char *)lang_pack.get() + total_len + 1;
2062 if (end <= lang_pack->data || !lang_pack->IsValid()) {
2066 std::array<uint, TEXT_TAB_END> tab_start, tab_num;
2070 uint16_t num = FROM_LE16(lang_pack->offsets[i]);
2073 tab_start[i] = count;
2079 std::vector<std::string_view> strings;
2082 char *s = lang_pack->data;
2083 for (uint i = 0; i < count; i++) {
2084 size_t len =
static_cast<uint8_t
>(*s++);
2085 if (s + len >= end)
return false;
2088 len = ((len & 0x3F) << 8) +
static_cast<uint8_t
>(*s++);
2089 if (s + len >= end)
return false;
2091 strings.emplace_back(s, len);
2094 assert(strings.size() == count);
2096 _langpack.langpack = std::move(lang_pack);
2097 _langpack.strings = std::move(strings);
2098 _langpack.langtab_num = tab_num;
2099 _langpack.langtab_start = tab_start;
2104 _langpack.list_separator =
GetString(STR_LIST_SEPARATOR);
2105 _langpack.ellipsis =
GetString(STR_TRUNCATION_ELLIPSIS);
2108 extern void Win32SetCurrentLocaleName(std::string iso_code);
2119 UErrorCode status = U_ZERO_ERROR;
2124 if (U_FAILURE(status)) {
2150#if !(defined(_WIN32) || defined(__APPLE__))
2161 auto env =
GetEnv(
"LANGUAGE");
2162 if (env.has_value())
return std::string{*env};
2165 if (env.has_value())
return std::string{*env};
2167 if (param !=
nullptr) {
2169 if (env.has_value())
return std::string{*env};
2173 if (env.has_value())
return std::string{*env};
2175 return std::nullopt;
2189 if (newgrflangid == lang.newgrflangid)
return ⟨
2204 if (!f.has_value())
return false;
2206 size_t read = fread(hdr,
sizeof(*hdr), 1, *f);
2208 bool ret = read == 1 && hdr->
IsValid();
2224 std::error_code error_code;
2225 for (
const auto &dir_entry : std::filesystem::directory_iterator(
OTTD2FS(path), error_code)) {
2226 if (!dir_entry.is_regular_file())
continue;
2227 if (dir_entry.path().extension() !=
".lng")
continue;
2230 lmd.
file = dir_entry.path();
2235 Debug(misc, 3,
"{} is not a valid language file", file);
2237 Debug(misc, 3,
"{}'s language ID is already known", file);
2243 Debug(misc, 9,
"Unable to open directory {}: {}", path, error_code.message());
2256 if (
_languages.empty()) UserError(
"No available language packs (invalid versions?)");
2260 std::string_view lang = str_lang.has_value() ? std::string_view{*str_lang} :
"en_GB";
2272 chosen_language = &lng;
2276 std::string_view iso_code = lng.isocode;
2277 if (iso_code ==
"en_GB") en_GB_fallback = &lng;
2280 if (!lng.IsReasonablyFinished())
continue;
2282 if (iso_code.starts_with(lang.substr(0, 5))) chosen_language = &lng;
2283 if (iso_code.starts_with(lang.substr(0, 2))) language_fallback = &lng;
2288 if (chosen_language ==
nullptr) {
2289 chosen_language = (language_fallback !=
nullptr) ? language_fallback : en_GB_fallback;
2301 return _langpack.langpack->isocode;
2313 for (
char32_t c :
Utf8View(*text)) {
2314 if (c >= SCC_FIRST_FONT && c <= SCC_LAST_FONT) {
2315 fs = (
FontSize)(c - SCC_FIRST_FONT);
2322 if (
IsInsideMM(c, SCC_SPRITE_START, SCC_SPRITE_END))
continue;
2358 std::string_view ret = _langpack.strings[_langpack.langtab_start[this->i] + this->j];
2385 if (searcher ==
nullptr) searcher = &pack_searcher;
2392#if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA)
2396 bool any_font_configured = !_fcsettings.medium.font.empty();
2404 _fcsettings = std::move(backup);
2406 if (!bad_font && any_font_configured) {
2410 std::string err_str;
2413 builder.
Put(
"The current font is missing some of the characters used in the texts for this language. Using system fallback font instead.");
2427 std::string err_str;
2430 builder.
Put(
"The current font is missing some of the characters used in the texts for this language. Go to Help & Manuals > Fonts, or read the file docs/fonts.md in your OpenTTD directory, to see how to solve this.");
2435#if !(defined(WITH_ICU_I18N) && defined(WITH_HARFBUZZ)) && !defined(WITH_UNISCRIBE) && !defined(WITH_COCOA)
2446 std::string err_str;
2449 builder.
Put(
"This version of OpenTTD does not support right-to-left languages. Recompile with ICU + Harfbuzz enabled.");
Class for backupping variables and making sure they are restored later.
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
bool IsValidCargoType(CargoType cargo)
Test whether cargo type is not INVALID_CARGO.
EnumBitSet< CargoType, uint64_t > CargoTypes
Bitset of CargoType elements.
CargoType
Cargo slots to indicate a cargo type within a game.
std::vector< const CargoSpec * > _sorted_cargo_specs
Cargo specifications sorted alphabetically by name.
void InitializeSortedCargoSpecs()
Initialize the list of sorted cargo specifications.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr bool Any(const Timpl &other) const
Test if any of the given values are set.
void PutUtf8(char32_t c)
Append UTF-8 char.
void Put(std::string_view str)
Append string.
void PutIntegerBase(T value, int base)
Append integer 'value' in given number 'base'.
void PutChar(char c)
Append 8-bit char.
void PutUint8(uint8_t value)
Append binary uint8.
virtual FontSize DefaultSize()=0
Get the default (font) size of the string.
virtual void Reset()=0
Reset the search, i.e.
BaseStringMissingGlyphSearcher(FontSizes fontsizes)
Create this string glyph searcher.
virtual std::optional< std::string_view > NextString()=0
Get the next string to search through.
void DetermineRequiredGlyphs(FontSizes fontsizes) override
Determine set of glyphs required for the current language.
Container for an encoded string, created by GetEncodedString.
friend EncodedString GetEncodedStringWithArgs(StringID str, std::span< const StringParameter > params)
Encode a string with its parameters into an encoded string.
std::string GetDecodedString() const
Decode the encoded string.
EncodedString ReplaceParam(size_t param, StringParameter &&value) const
Replace a parameter of this EncodedString.
Iterate a range of enum values.
static std::optional< FileHandle > Open(const std::string &filename, std::string_view mode)
Open an RAII file handle if possible.
Font cache for basic fonts.
virtual GlyphID MapCharToGlyph(char32_t key, bool fallback=true)=0
Map a character into a glyph.
static void LoadFontCaches(FontSizes fontsizes)
(Re)initialize the font cache related things, i.e.
static FontCache * Get(FontSize fs)
Get the font cache of a given font size.
static bool FindFallbackFont(const std::string &language_isocode, MissingGlyphSearcher *callback)
We would like to have a fallback font as the current one doesn't contain all characters we need.
Helper for searching through the language pack.
LanguagePackGlyphSearcher()
Create this language pack glyph searcher.
uint j
Iterator for the secondary language tables.
std::optional< std::string_view > NextString() override
Get the next string to search through.
FontSize DefaultSize() override
Get the default (font) size of the string.
uint i
Iterator for the primary language tables.
void Reset() override
Reset the search, i.e.
static void Initialize()
Perform initialization of layout engine.
A searcher for missing glyphs.
const FontSizes fontsizes
Font sizes this searcher will try to find.
virtual void DetermineRequiredGlyphs(FontSizes fontsizes)=0
Determine set of glyphs required for the current language.
std::set< char32_t > missing_glyphs
Glyphs to search for.
FontSizes missing_fontsizes
Font sizes to actually search for.
Compose data into a growing std::string.
back_insert_iterator back_inserter()
Create a back-insert-iterator.
Parse data from a string / buffer.
std::optional< T > TryReadIntegerBase(int base, bool clamp=false)
Try to read and parse an integer in number 'base', and then advance the reader.
bool PeekUtf8If(char32_t c) const
Check whether the next UTF-8 char matches 'c'.
char32_t ReadUtf8(char32_t def='?')
Read UTF-8 character, and advance reader.
@ SKIP_ONE_SEPARATOR
Read and discard one separator, do not include it in the result.
@ KEEP_SEPARATOR
Keep the separator in the data as next value to be read.
bool AnyBytesLeft() const noexcept
Check whether any bytes left to read.
uint8_t ReadUint8(uint8_t def=0)
Read binary uint8, and advance reader.
uint16_t ReadUint16LE(uint16_t def=0)
Read binary uint16 using little endian, and advance reader.
void SkipAll()
Discard all remaining data.
T ReadIntegerBase(int base, T def=0, bool clamp=false)
Read and parse an integer in number 'base', and advance the reader.
std::string_view Read(size_type len)
Read the next 'len' bytes, and advance reader.
bool ReadUtf8If(char32_t c)
Check whether the next UTF-8 char matches 'c', and skip it.
static constexpr size_type npos
Special value for "end of data".
void Skip(size_type len)
Discard some bytes.
void SkipUtf8If(char32_t c)
If the next data matches the UTF-8 char 'c', then skip it.
std::string_view ReadUntilUtf8(char32_t c, SeparatorUsage sep)
Read data until the first occurrence of UTF-8 char 'c', and advance reader.
void SetOffset(size_t offset)
Set the offset within the string from where to return the next result of GetInt64 or GetInt32.
std::string_view GetNextParameterString()
Get the next string parameter from our parameters.
StringParameters GetRemainingParameters()
Get a new instance of StringParameters that is a "range" into the remaining existing parameters.
std::span< StringParameter > parameters
Array with the actual parameters.
const StringParameter & GetNextParameterReference()
Get the next parameter from our parameters.
void AdvanceOffset(size_t advance)
Advance the offset within the string from where to return the next result of GetInt64 or GetInt32.
uint64_t GetNextParameter()
Get the next parameter from our parameters.
size_t offset
Current offset in the parameters span.
char32_t next_type
The type of the next data that is retrieved.
size_t GetOffset()
Get the current offset, so it can be backed up for certain processing steps, or be used to offset the...
size_t GetNumParameters() const
Return the number of parameters.
size_t GetDataLeft() const
Return the amount of elements which can still be read.
char32_t GetTypeAtOffset(size_t offset) const
Get the type of a specific element.
static YearMonthDay ConvertDateToYMD(Date date)
Converts a Date to a Year, Month & Day.
static bool UsingWallclockUnits(bool newgame=false)
Check if we are using wallclock units.
StrongType::Typedef< int32_t, DateTag< struct Calendar >, StrongType::Compare, StrongType::Integer > Date
Constant span of UTF-8 encoded data.
Definition of stuff that is very close to a company, like the company struct itself.
Control codes that are embedded in the translation strings.
StringControlCode
List of string control codes used for string formatting, displaying, and by strgen to generate the la...
@ SCC_ENCODED
Encoded string marker and sub-string parameter.
@ SCC_ENCODED_NUMERIC
Encoded numeric parameter.
@ SCC_ENCODED_STRING
Encoded string parameter.
@ SCC_NEWGRF_STRINL
Inline another string at the current position, StringID is encoded in the string.
@ SCC_NEWGRF_FIRST
The next variables are part of a NewGRF subsystem for creating text strings.
@ SCC_NEWGRF_PRINT_WORD_STRING_ID
81: Read 2 bytes from the stack as String ID
@ SCC_ENCODED_INTERNAL
Encoded text from OpenTTD.
Functions to handle different currencies.
const CurrencySpec & GetCurrency()
Get the currently selected currency.
@ Suffix
Show the suffix value.
@ Prefix
Show the prefix value.
Functions related to debugging.
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Base for all depots (except hangars).
PoolID< uint16_t, struct DepotIDTag, 64000, 0xFFFF > DepotID
Type for the unique identifier of depots.
Function to handling different endian machines.
PoolID< uint16_t, struct EngineIDTag, 64000, 0xFFFF > EngineID
Unique identification number of an engine.
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23).
Functions related to errors.
@ Warning
Other information.
@ Error
Errors (eg. saving/loading failed).
void ShowErrorMessage(EncodedString &&summary_msg, int x, int y, CommandCost &cc)
Display an error message in a window.
Error reporting related functions.
std::unique_ptr< char[]> ReadFileToMem(const std::string &filename, size_t &lenp, size_t maxsize)
Load a file into memory.
Functions for standard in/out file operations.
Searchpath
Types of searchpaths OpenTTD might use.
@ Lang
Subdirectory for all translation files.
void ReconsiderGameScriptLanguage()
Reconsider the game script language, so we use the right one.
std::string_view GetGameStringPtr(StringIndexInTab id)
Get the string pointer of a particular game string.
Base functions regarding game texts.
std::pair< uint8_t, uint8_t > GetBroadestDigit(FontSize size)
Determine the broadest digits for guessing the maximum width of a n-digit number.
void LoadStringWidthTable(FontSizes fontsizes)
Initialize _stringwidth_table cache for the specified font sizes.
Functions related to laying out the texts.
FontSize
Available font sizes.
@ Normal
Index of the normal font in the font tables.
Colours
One of 16 base colours used for companies and windows/widgets.
EnumBitSet< FontSize, uint8_t > FontSizes
Bitset of FontSize elements.
constexpr FontSizes FONTSIZES_REQUIRED
Mask of font sizes required to be present.
static constexpr GroupID DEFAULT_GROUP
Ungrouped vehicles are in this group.
const IndustrySpec * GetIndustrySpec(IndustryType thistype)
Accessor for array _industry_specs.
void SortIndustryTypes()
Initialize the list of sorted industry types.
@ Toyland
Landscape with funky industries and vehicles.
Information about languages and their files.
LanguageList _languages
The actual list of language meta data.
const LanguageMetadata * _current_language
The currently loaded language.
static const uint8_t MAX_NUM_GENDERS
Maximum number of supported genders.
std::unique_ptr< icu::Collator > _current_collator
Collator for the language currently in use.
std::vector< LanguageMetadata > LanguageList
Type for the list of language meta data.
static const uint8_t MAX_NUM_CASES
Maximum number of supported cases.
constexpr bool IsInsideMM(const size_t x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
constexpr uint64_t PowerOfTen(int power)
Computes ten to the given power.
void BuildContentTypeStringList()
Build array of all strings corresponding to the content types.
User interface for downloading files.
@ CBID_VEHICLE_NAME
Called to determine the engine name to show.
uint16_t GetVehicleCallback(CallbackID callback, uint32_t param1, uint32_t param2, EngineID engine, const Vehicle *v, std::span< int32_t > regs100)
Evaluate a newgrf callback for vehicles.
Functions for NewGRF engines.
std::string_view GetGRFStringPtr(StringIndexInTab stringid)
Get a C-string from a stringid set by a newgrf.
std::string GetGRFStringWithTextStack(const struct GRFFile *grffile, GRFStringID grfstringid, std::span< const int32_t > textstack)
Format a GRF string using the text ref stack for parameters.
char32_t RemapNewGRFStringControlCode(char32_t scc, StringConsumer &consumer)
Emit OpenTTD's internal string code for the different NewGRF string codes.
Header of Action 04 "universal holder" structure and functions.
StrongType::Typedef< uint32_t, struct GRFStringIDTag, StrongType::Compare, StrongType::Integer > GRFStringID
Type for GRF-internal string IDs.
static constexpr GRFStringID GRFSTR_MISC_GRF_TEXT
Miscellaneous GRF text range.
Declaration of OTTD revision dependent variables.
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
PoolID< uint16_t, struct SignIDTag, 64000, 0xFFFF > SignID
The type of the IDs of signs.
void BuildIndustriesLegend()
Fills an array for the industries legends.
Base classes/functions for stations.
@ Dock
Station with a dock.
@ TruckStop
Station with truck stops.
@ Train
Station with train station.
@ Airport
Station with an airport.
@ BusStop
Station with bus stops.
EnumBitSet< StationFacility, uint8_t > StationFacilities
Bitset of StationFacility elements.
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
std::optional< std::string_view > GetEnv(const char *variable)
Get the environment variable using std::getenv and when it is an empty string (or nullptr),...
bool StrValid(std::span< const char > str)
Checks whether the given string is valid, i.e.
Functions related to low-level strings.
bool IsTextDirectionChar(char32_t c)
Is the given character a text direction character.
void MacOSSetCurrentLocaleName(std::string_view iso_code)
Store current language locale as a CoreFoundation locale.
#define NBSP
A non-breaking space.
uint64_t GetParamMaxValue(uint64_t max_value, uint min_count, FontSize size)
Get some number that is suitable for string size computations.
static void FormatNumber(StringBuilder &builder, int64_t number, std::string_view separator)
Format a number into a string.
EncodedString GetEncodedStringWithArgs(StringID str, std::span< const StringParameter > params)
Encode a string with its parameters into an encoded string.
void GetStringWithArgs(StringBuilder &builder, StringID string, StringParameters &args, uint case_index, bool game_script)
Get a parsed string with most special stringcodes replaced by the string parameters.
std::optional< std::string > GetCurrentLocale(const char *param)
Determine the current charset based on the environment First check some default values,...
std::string_view GetListSeparator()
Get the list separator string for the current language.
static const Units _units_height[]
Unit conversions for height.
static void FormatBytes(StringBuilder &builder, int64_t number)
Format a given number as a number of bytes with the SI prefix.
void AppendStringInPlace(std::string &result, StringID string)
Resolve the given StringID and append in place into an existing std::string with formatting but no pa...
uint ConvertSpeedToDisplaySpeed(uint speed, VehicleType type)
Convert the given (internal) speed to the display speed.
std::string _config_language_file
The file (name) stored in the configuration.
static const Units GetVelocityUnits(VehicleType type)
Get the correct velocity units depending on the vehicle type and whether we're using real-time units.
static int DeterminePluralForm(int64_t count, uint plural_form)
Determine the "plural" index given a plural form and a number.
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
uint ConvertDisplaySpeedToKmhishSpeed(uint speed, VehicleType type)
Convert the given display speed to the km/h-ish speed.
static const Units _units_power[]
Unit conversions for power.
static std::string_view GetSurname(uint32_t seed)
Get the surname of the president with the given seed.
void CheckForMissingGlyphs(MissingGlyphSearcher *searcher)
Check whether the currently loaded language pack uses characters that the currently loaded font does ...
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
std::string_view GetCurrentLanguageIsoCode()
Get the ISO language code of the currently loaded language.
static bool _scan_for_gender_data
Are we scanning for the gender of the current string? (instead of formatting it).
static const UnitsLong _units_volume[]
Unit conversions for volume.
static void DecodeEncodedString(StringConsumer &consumer, bool game_script, StringBuilder &builder)
Decodes an encoded string during FormatString.
static const UnitsLong _units_weight[]
Unit conversions for weight.
static const Units _units_velocity_calendar[]
Unit conversions for velocity.
static void FillLanguageList(const std::string &path)
Search for the languages in the given directory and add them to the _languages list.
uint ConvertKmhishSpeedToDisplaySpeed(uint speed, VehicleType type)
Convert the given km/h-ish speed to the display speed.
static const Units _units_force[]
Unit conversions for force.
void InitializeLanguagePacks()
Make a list of the available language packs.
const LanguageMetadata * GetLanguage(uint8_t newgrflangid)
Get the language with the given NewGRF language ID.
static bool IsColourSafe(std::string_view buffer)
Test if a string contains colour codes, and is not wrapped by push/pop codes.
static const Units _units_time_days_or_seconds[]
Unit conversions for time in calendar days or wallclock seconds.
uint ConvertDisplaySpeedToSpeed(uint speed, VehicleType type)
Convert the given display speed to the (internal) speed.
TextDirection _current_text_dir
Text direction of the currently selected language.
static const Units _units_velocity_realtime[]
Unit conversions for velocity.
bool ReadLanguagePack(const LanguageMetadata *lang)
Read a particular language.
static bool GetLanguageFileHeader(const std::string &file, LanguagePackHeader *hdr)
Reads the language file header and checks compatibility.
static const Units _units_time_months_or_minutes[]
Unit conversions for time in calendar months or wallclock minutes.
static void FormatString(StringBuilder &builder, std::string_view str, StringParameters &args, uint case_index=0, bool game_script=false, bool dry_run=false)
Parse most format codes within a string and write the result to a buffer.
static const Units _units_time_years_or_minutes[]
Unit conversions for time in calendar years or wallclock minutes.
static const Units _units_power_to_weight[]
Unit conversions for power to weight.
uint64_t GetParamMaxDigits(uint count, FontSize size)
Get some number that is suitable for string size computations.
std::string_view GetEllipsis()
Get the ellipsis string for the current language.
static const Units _units_time_years_or_periods[]
Unit conversions for time in calendar years or economic periods.
Functions related to OTTD's strings.
StringTab GetStringTab(StringID str)
Extract the StringTab from a StringID.
auto MakeParameters(Args &&... args)
Helper to create the StringParameters with its own buffer with the given parameter values.
StringID MakeStringID(StringTab tab, StringIndexInTab index)
Create a StringID.
StringIndexInTab GetStringIndex(StringID str)
Extract the StringIndex from a StringID.
Types and functions related to the internal workings of formatting OpenTTD's strings.
void GenerateTownNameString(StringBuilder &builder, size_t lang, uint32_t seed)
Generates town name from given seed.
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
StrongType::Typedef< uint32_t, struct StringIndexInTabTag, StrongType::Compare, StrongType::Integer > StringIndexInTab
The index/offset of a string within a StringTab.
static constexpr StringID SPECSTR_COMPANY_NAME_START
Special strings for company names on the form "TownName transport".
static constexpr StringID SPECSTR_SILLY_NAME
Special string for silly company names.
static const uint TAB_SIZE_GAMESCRIPT
Number of strings for GameScripts.
static const uint MAX_LANG
Maximum number of languages supported by the game, and the NewGRF specs.
static constexpr StringID SPECSTR_ANDCO_NAME
Special string for Surname & Co company names.
static constexpr StringID SPECSTR_PRESIDENT_NAME
Special string for the president's name.
static constexpr StringID SPECSTR_TOWNNAME_START
Special strings for town names.
static const uint TAB_SIZE
Number of strings per StringTab.
StringTab
StringTabs to group StringIDs.
@ TEXT_TAB_NEWGRF_START
Start of NewGRF supplied strings.
@ TEXT_TAB_GAMESCRIPT_START
Start of GameScript supplied strings.
@ TEXT_TAB_END
End of language files.
TextDirection
Directions a text can go to.
@ TD_LTR
Text is written left-to-right by default.
Class to backup a specific variable and restore it upon destruction of this object to prevent stack v...
std::string name
Name of vehicle.
StringID string_id
Default name (town area) of station.
Town * town
The town this station is associated with.
std::string name
Custom name.
VehicleType type
Type of vehicle.
StringID units_volume
Name of a single unit of cargo of this type.
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo type.
static size_t GetArraySize()
Total number of cargospecs, both valid and invalid.
std::string president_name
Name of the president if the user changed it.
uint32_t name_2
Parameter of name_1.
uint32_t president_name_2
Parameter of president_name_1.
StringID name_1
Name of the company if the user did not change it.
StringID president_name_1
Name of the president if the user did not change it.
std::string name
Name of the company if the user changed it.
static bool IsValidHumanID(auto index)
Is this company a valid company, not controlled by a NoAI program?
Specification of a currency.
std::string separator
The thousands separator for this currency.
CurrencySymbolPositions symbol_pos
Which currency symbols should we show?
std::string prefix
Prefix to apply when formatting money in this currency.
std::string suffix
Suffix to apply when formatting money in this currency.
uint16_t rate
The conversion rate compared to the base currency.
uint16_t town_cn
The N-1th depot for this town (consecutive number).
Settings for the four different fonts.
Dynamic data of a loaded NewGRF.
std::string name
Group Name.
uint16_t number
Per-company group number.
Defines the data structure for constructing industry.
StringID name
Displayed name of the industry.
StringID station_name
Default name for nearby station.
Defines the internal data of a functional industry.
IndustryType type
type of industry.
char data[]
List of strings.
std::string list_separator
Current list separator string.
std::string ellipsis
Current ellipsis string.
std::array< uint, TEXT_TAB_END > langtab_num
Offset into langpack offs.
std::array< uint, TEXT_TAB_END > langtab_start
Offset into langpack offs.
static Depot * Get(auto index)
static Company * GetIfValid(auto index)
static Station * GetIfValid(auto index)
The data required to format and validate a single parameter of a string.
std::string name
Custom town name. If empty, the town was not renamed and uses the generated name.
Helper for unit conversion.
double factor
Amount to multiply or divide upon conversion.
int64_t ToDisplay(int64_t input, bool round=true) const
Convert value from OpenTTD's internal unit into the displayed value.
int64_t FromDisplay(int64_t input, bool round=true, int64_t divider=1) const
Convert the displayed value back into a value of OpenTTD's internal unit.
Information about a specific unit system with a long variant.
StringID s
String for the short variant of the unit.
StringID l
String for the long variant of the unit.
unsigned int decimal_places
Number of decimal places embedded in the value. For example, 1 if the value is in tenths,...
UnitConversion c
Conversion.
Information about a specific unit system.
StringID s
String for the unit.
unsigned int decimal_places
Number of decimal places embedded in the value. For example, 1 if the value is in tenths,...
UnitConversion c
Conversion.
GroupID group_id
Index of group Pool array.
UnitID unitnumber
unit number, for display purposes only
Representation of a waypoint.
uint16_t town_cn
The N-1th waypoint for this town (consecutive number).
Definition of the game-calendar-timer.
Town name generator stuff.
std::pair< size_t, char32_t > DecodeUtf8(std::string_view buf)
Decode a character from UTF-8.
Handling of UTF-8 encoded data.
Base class for all vehicles.
PoolID< uint32_t, struct VehicleIDTag, 0xFF000, 0xFFFFF > VehicleID
The type all our vehicle IDs have.
VehicleType
Available vehicle types.
@ Aircraft
Aircraft vehicle type.
@ Train
Train vehicle type.
std::wstring OTTD2FS(std::string_view name)
Convert from OpenTTD's encoding to a wide string.
std::string FS2OTTD(std::wstring_view name)
Convert to OpenTTD's encoding from a wide string.
void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope)
Mark window data of all windows of a given class as invalid (in need of re-computing) Note that by de...
Window functions not directly related to making/drawing windows.