45#include "table/strings.h"
47#include "3rdparty/fmt/std.h"
49#include "strings_internal.h"
73 throw std::out_of_range(
"Trying to read invalid string parameter");
77 if (param.type != 0 && param.type != this->next_type) {
79 throw std::out_of_range(
"Trying to read string parameter with wrong type");
113 void operator()(
const std::monostate &) {}
115 void operator()(
const uint64_t &arg)
121 void operator()(
const std::string &value)
131 this->builder += value;
136 for (
const auto ¶m : params) {
137 builder.
PutUtf8(SCC_RECORD_SEPARATOR);
138 std::visit(v, param.data);
153 if (this->empty())
return {};
155 std::vector<StringParameter> params;
158 const char *p = this->
string.data();
159 const char *e = this->
string.data() + this->
string.length();
161 char32_t c = Utf8Consume(p);
165 auto result = std::from_chars(p, e, str, 16);
166 if (result.ec != std::errc())
return {};
167 if (result.ptr != e && *result.ptr != SCC_RECORD_SEPARATOR)
return {};
174 for (; p != e && *p != SCC_RECORD_SEPARATOR; ++p) {}
178 params.emplace_back(std::monostate{});
183 char32_t parameter_type;
187 switch (parameter_type) {
190 result = std::from_chars(s, p, value, 16);
191 if (result.ec != std::errc() || result.ptr != p)
return {};
192 params.emplace_back(value);
197 params.emplace_back(std::string(s, p));
203 params.emplace_back(std::monostate{});
208 if (param >= std::size(params))
return {};
209 params[param] = data;
219 return GetString(STR_JUST_RAW_STRING, this->
string);
231 uint64_t val = count > 1 ? front : next;
232 for (; count > 1; count--) {
233 val = 10 * val + next;
249 while (max_value >= 10) {
271static void FormatString(
StringBuilder &builder, std::string_view str, std::span<StringParameter> params, uint case_index = 0,
bool game_script =
false,
bool dry_run =
false)
274 FormatString(builder, str, tmp_params, case_index, game_script, dry_run);
285 delete[]
reinterpret_cast<char*
>(langpack);
290 std::unique_ptr<LanguagePack, LanguagePackDeleter> langpack;
292 std::vector<std::string_view> strings;
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:
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 const char *GetDecimalSeparator()
472 if (
StrEmpty(decimal_separator)) 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)
513 if (
StrEmpty(separator)) 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 const char *
const 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));
565static void FormatYmdString(
StringBuilder &builder, TimerGameCalendar::Date date, uint case_index)
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);
573static void FormatMonthAndYear(
StringBuilder &builder, TimerGameCalendar::Date date, uint 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);
617 if (number >=
Money(1'000'000'000'000'000) - 500'000'000) {
618 number = (number +
Money(500'000'000'000)) /
Money(1'000'000'000'000);
619 number_str = STR_CURRENCY_SHORT_TERA;
620 }
else if (number >=
Money(1'000'000'000'000) - 500'000) {
621 number = (number + 500'000'000) / 1'000'000'000;
622 number_str = STR_CURRENCY_SHORT_GIGA;
623 }
else if (number >= 1'000'000'000 - 500) {
624 number = (number + 500'000) / 1'000'000;
625 number_str = STR_CURRENCY_SHORT_MEGA;
626 }
else if (number >= 1'000'000) {
627 number = (number + 500) / 1'000;
628 number_str = STR_CURRENCY_SHORT_KILO;
634 if (
StrEmpty(separator)) separator = _langpack.langpack->digit_group_separator_currency;
636 if (number_str != STR_NULL) {
646 builder.
PutUtf8(SCC_POP_COLOUR);
659 uint64_t n =
abs(count);
661 switch (plural_form) {
670 return n != 1 ? 1 : 0;
682 return n > 1 ? 1 : 0;
689 return n % 10 == 1 && n % 100 != 11 ? 0 : n != 0 ? 1 : 2;
695 return n == 1 ? 0 : n == 2 ? 1 : n < 7 ? 2 : n < 11 ? 3 : 4;
701 return n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
707 return n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
713 return n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
719 return n % 100 == 1 ? 0 : n % 100 == 2 ? 1 : n % 100 == 3 || n % 100 == 4 ? 2 : 3;
725 return n % 10 == 1 && n % 100 != 11 ? 0 : 1;
731 return n == 1 ? 0 : n >= 2 && n <= 4 ? 1 : 2;
762 return (n == 1 ? 0 : n == 0 || (n % 100 > 1 && n % 100 < 11) ? 1 : (n % 100 > 10 && n % 100 < 20) ? 2 : 3);
767 return ((n == 1 || n == 11) ? 0 : (n == 2 || n == 12) ? 1 : ((n > 2 && n < 11) || (n > 12 && n < 20)) ? 2 : 3);
773 return n == 1 ? 0 : (n == 0 || (n % 100 > 0 && n % 100 < 20)) ? 1 : 2;
777static const char *ParseStringChoice(
const char *b, uint form,
StringBuilder &builder)
780 uint n = (uint8_t)*b++;
781 size_t form_offset = 0, form_len = 0, total_len = 0;
782 for (uint i = 0; i != n; i++) {
783 uint len = (uint8_t)*b++;
785 form_offset = total_len;
791 builder += std::string_view(b + form_offset, form_len);
792 return b + total_len;
805 int64_t
ToDisplay(int64_t input,
bool round =
true)
const
808 ? (int64_t)std::round(input * this->factor)
809 : (int64_t)(input * this->factor);
819 int64_t
FromDisplay(int64_t input,
bool round =
true, int64_t divider = 1)
const
822 ? (int64_t)std::round(input / this->factor / divider)
823 : (int64_t)(input / this->factor / divider);
844 { { 1.0 }, STR_UNITS_VELOCITY_IMPERIAL, 0 },
845 { { 1.609344 }, STR_UNITS_VELOCITY_METRIC, 0 },
846 { { 0.44704 }, STR_UNITS_VELOCITY_SI, 0 },
847 { { 0.578125 }, STR_UNITS_VELOCITY_GAMEUNITS_DAY, 1 },
848 { { 0.868976 }, STR_UNITS_VELOCITY_KNOTS, 0 },
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.289352 }, STR_UNITS_VELOCITY_GAMEUNITS_SEC, 1 },
857 { { 0.868976 }, STR_UNITS_VELOCITY_KNOTS, 0 },
862 { { 1.0 }, STR_UNITS_POWER_IMPERIAL, 0 },
863 { { 1.01387 }, STR_UNITS_POWER_METRIC, 0 },
864 { { 0.745699 }, STR_UNITS_POWER_SI, 0 },
869 { { 0.907185 }, STR_UNITS_POWER_IMPERIAL_TO_WEIGHT_IMPERIAL, 1 },
870 { { 1.0 }, STR_UNITS_POWER_IMPERIAL_TO_WEIGHT_METRIC, 1 },
871 { { 1.0 }, STR_UNITS_POWER_IMPERIAL_TO_WEIGHT_SI, 1 },
872 { { 0.919768 }, STR_UNITS_POWER_METRIC_TO_WEIGHT_IMPERIAL, 1 },
873 { { 1.01387 }, STR_UNITS_POWER_METRIC_TO_WEIGHT_METRIC, 1 },
874 { { 1.01387 }, STR_UNITS_POWER_METRIC_TO_WEIGHT_SI, 1 },
875 { { 0.676487 }, STR_UNITS_POWER_SI_TO_WEIGHT_IMPERIAL, 1 },
876 { { 0.745699 }, STR_UNITS_POWER_SI_TO_WEIGHT_METRIC, 1 },
877 { { 0.745699 }, STR_UNITS_POWER_SI_TO_WEIGHT_SI, 1 },
882 { { 1.102311 }, STR_UNITS_WEIGHT_SHORT_IMPERIAL, STR_UNITS_WEIGHT_LONG_IMPERIAL, 0 },
883 { { 1.0 }, STR_UNITS_WEIGHT_SHORT_METRIC, STR_UNITS_WEIGHT_LONG_METRIC, 0 },
884 { { 1000.0 }, STR_UNITS_WEIGHT_SHORT_SI, STR_UNITS_WEIGHT_LONG_SI, 0 },
889 { { 264.172 }, STR_UNITS_VOLUME_SHORT_IMPERIAL, STR_UNITS_VOLUME_LONG_IMPERIAL, 0 },
890 { { 1000.0 }, STR_UNITS_VOLUME_SHORT_METRIC, STR_UNITS_VOLUME_LONG_METRIC, 0 },
891 { { 1.0 }, STR_UNITS_VOLUME_SHORT_SI, STR_UNITS_VOLUME_LONG_SI, 0 },
896 { { 0.224809 }, STR_UNITS_FORCE_IMPERIAL, 0 },
897 { { 0.101972 }, STR_UNITS_FORCE_METRIC, 0 },
898 { { 0.001 }, STR_UNITS_FORCE_SI, 0 },
903 { { 3.0 }, STR_UNITS_HEIGHT_IMPERIAL, 0 },
904 { { 1.0 }, STR_UNITS_HEIGHT_METRIC, 0 },
905 { { 1.0 }, STR_UNITS_HEIGHT_SI, 0 },
910 { { 1 }, STR_UNITS_DAYS, 0 },
911 { { 2 }, STR_UNITS_SECONDS, 0 },
916 { { 1 }, STR_UNITS_MONTHS, 0 },
917 { { 1 }, STR_UNITS_MINUTES, 0 },
922 { { 1 }, STR_UNITS_YEARS, 0 },
923 { { 1 }, STR_UNITS_PERIODS, 0 },
928 { { 1 }, STR_UNITS_YEARS, 0 },
929 { { 12 }, STR_UNITS_MINUTES, 0 },
1001 std::vector<StringParameter> sub_args;
1005 if (*p != SCC_RECORD_SEPARATOR && *p !=
'\0') {
1006 while (*p !=
'\0') p++;
1007 builder +=
"(invalid SCC_ENCODED)";
1011 while (*p !=
'\0') p++;
1012 builder +=
"(invalid StringID)";
1016 while (*p !=
'\0') {
1018 const char *s = ++p;
1021 for (; *p !=
'\0' && *p != SCC_RECORD_SEPARATOR; ++p) {}
1025 sub_args.emplace_back(std::monostate{});
1030 char32_t parameter_type;
1034 switch (parameter_type) {
1036 uint64_t param = std::strtoull(s, &p, 16);
1038 while (*p !=
'\0') p++;
1039 builder +=
"(invalid sub-StringID)";
1043 sub_args.emplace_back(param);
1048 uint64_t param = std::strtoull(s, &p, 16);
1049 sub_args.emplace_back(param);
1054 sub_args.emplace_back(std::string(s, p - s));
1060 sub_args.emplace_back(std::monostate{});
1080 size_t orig_first_param_offset = args.
GetOffset();
1093 FormatString(dry_run_builder, str_arg, args, orig_case_index, game_script,
true);
1095 args.
SetOffset(orig_first_param_offset);
1097 uint next_substr_case_index = 0;
1098 struct StrStackItem {
1101 size_t first_param_offset;
1104 StrStackItem(std::string_view view,
size_t first_param_offset, uint case_index)
1105 : str(view.data()), end(view.data() + view.size()), first_param_offset(first_param_offset), case_index(case_index)
1108 std::stack<StrStackItem, std::vector<StrStackItem>> str_stack;
1109 str_stack.emplace(str_arg, orig_first_param_offset, orig_case_index);
1113 while (!str_stack.empty() && str_stack.top().str >= str_stack.top().end) {
1116 if (str_stack.empty())
break;
1117 const char *&str = str_stack.top().str;
1118 const size_t ref_param_offset = str_stack.top().first_param_offset;
1119 const uint case_index = str_stack.top().case_index;
1120 char32_t b = Utf8Consume(&str);
1126 if (b == 0)
continue;
1129 if (b < SCC_CONTROL_START || b > SCC_CONTROL_END) {
1134 args.SetTypeOfNextParameter(b);
1142 StringID substr = Utf8Consume(&str);
1143 std::string_view ptr = GetStringPtr(substr);
1144 str_stack.emplace(ptr, args.
GetOffset(), next_substr_case_index);
1145 next_substr_case_index = 0;
1151 std::string_view ptr = GetStringPtr(substr);
1152 str_stack.emplace(ptr, args.
GetOffset(), next_substr_case_index);
1153 next_substr_case_index = 0;
1157 case SCC_GENDER_LIST: {
1159 size_t offset = ref_param_offset + (uint8_t)*str++;
1163 builder +=
"(invalid GENDER parameter)";
1183 const char *s = buffer.c_str();
1184 char32_t c = Utf8Consume(&s);
1186 if (c == SCC_GENDER_INDEX) gender = (uint8_t)s[0];
1188 str = ParseStringChoice(str, gender, builder);
1194 case SCC_GENDER_INDEX:
1196 builder.
PutUtf8(SCC_GENDER_INDEX);
1203 case SCC_PLURAL_LIST: {
1204 int plural_form = *str++;
1205 size_t offset = ref_param_offset + (uint8_t)*str++;
1206 const uint64_t *v =
nullptr;
1209 v = std::get_if<uint64_t>(&args.GetParam(offset));
1212 str = ParseStringChoice(str,
DeterminePluralForm(
static_cast<int64_t
>(*v), plural_form), builder);
1214 builder +=
"(invalid PLURAL parameter)";
1219 case SCC_ARG_INDEX: {
1220 args.
SetOffset(ref_param_offset + (uint8_t)*str++);
1224 case SCC_SET_CASE: {
1227 next_substr_case_index = (uint8_t)*str++;
1231 case SCC_SWITCH_CASE: {
1234 uint num = (uint8_t)*str++;
1235 std::optional<std::string_view> found;
1236 for (; num > 0; --num) {
1237 uint8_t index =
static_cast<uint8_t
>(str[0]);
1238 uint16_t len =
static_cast<uint8_t
>(str[1]) + (
static_cast<uint8_t
>(str[2]) << 8);
1240 if (index == case_index) {
1242 found.emplace(str, len);
1246 uint16_t default_len =
static_cast<uint8_t
>(str[0]) + (
static_cast<uint8_t
>(str[1]) << 8);
1248 if (!found.has_value()) found.emplace(str, default_len);
1250 assert(str <= str_stack.top().end);
1251 str_stack.emplace(*found, ref_param_offset, case_index);
1256 builder += _openttd_revision;
1259 case SCC_RAW_STRING_POINTER: {
1262 if (raw_string ==
nullptr) {
1263 builder +=
"(invalid RAW_STRING parameter)";
1275 GetStringWithArgs(builder, string_id, tmp_params, next_substr_case_index, game_script);
1276 next_substr_case_index = 0;
1290 uint size = b - SCC_STRING1 + 1;
1292 builder +=
"(consumed too many parameters)";
1295 GetStringWithArgs(builder, string_id, sub_args, next_substr_case_index, game_script);
1298 next_substr_case_index = 0;
1310 FormatCommaNumber(builder, number);
1315 int64_t fractional = number % divisor;
1317 FormatCommaNumber(builder, number);
1318 fmt::format_to(builder.
back_inserter(),
"{}{:0{}d}", GetDecimalSeparator(), fractional, digits);
1326 case SCC_ZEROFILL_NUM: {
1340 case SCC_CARGO_TINY: {
1349 switch (cargo_str) {
1364 FormatCommaNumber(builder, amount);
1368 case SCC_CARGO_SHORT: {
1376 switch (cargo_str) {
1402 case SCC_CARGO_LONG: {
1413 case SCC_CARGO_LIST: {
1419 if (!
HasBit(cmask, cs->Index()))
continue;
1425 builder += list_separator;
1428 GetStringWithArgs(builder, cs->name, args, next_substr_case_index, game_script);
1432 if (first)
GetStringWithArgs(builder, STR_JUST_NOTHING, args, next_substr_case_index, game_script);
1434 next_substr_case_index = 0;
1438 case SCC_CURRENCY_SHORT:
1442 case SCC_CURRENCY_LONG:
1447 FormatTinyOrISODate(builder, args.
GetNextParameter<TimerGameCalendar::Date>(), STR_FORMAT_DATE_TINY);
1450 case SCC_DATE_SHORT:
1451 FormatMonthAndYear(builder, args.
GetNextParameter<TimerGameCalendar::Date>(), next_substr_case_index);
1452 next_substr_case_index = 0;
1456 FormatYmdString(builder, args.
GetNextParameter<TimerGameCalendar::Date>(), next_substr_case_index);
1457 next_substr_case_index = 0;
1461 FormatTinyOrISODate(builder, args.
GetNextParameter<TimerGameCalendar::Date>(), STR_FORMAT_DATE_ISO);
1488 case SCC_POWER_TO_WEIGHT: {
1497 case SCC_VELOCITY: {
1507 case SCC_VOLUME_SHORT: {
1515 case SCC_VOLUME_LONG: {
1523 case SCC_WEIGHT_SHORT: {
1531 case SCC_WEIGHT_LONG: {
1539 case SCC_UNITS_DAYS_OR_SECONDS: {
1547 case SCC_UNITS_MONTHS_OR_MINUTES: {
1555 case SCC_UNITS_YEARS_OR_PERIODS: {
1563 case SCC_UNITS_YEARS_OR_MINUTES: {
1571 case SCC_COMPANY_NAME: {
1573 if (c ==
nullptr)
break;
1575 if (!c->
name.empty()) {
1585 case SCC_COMPANY_NUM: {
1596 case SCC_DEPOT_NAME: {
1605 if (!d->name.empty()) {
1615 case SCC_ENGINE_NAME: {
1618 if (e ==
nullptr)
break;
1620 if (!e->name.empty() && e->IsEnabled()) {
1630 const GRFFile *grffile = e->GetGRF();
1631 assert(grffile !=
nullptr);
1642 case SCC_GROUP_NAME: {
1644 if (g ==
nullptr)
break;
1646 if (!g->
name.empty()) {
1656 case SCC_INDUSTRY_NAME: {
1658 if (i ==
nullptr)
break;
1660 static bool use_cache =
true;
1665 }
else if (use_cache) {
1667 builder += i->GetCachedName();
1671 FormatString(builder, GetStringPtr(STR_FORMAT_INDUSTRY_NAME), tmp_params, next_substr_case_index);
1673 next_substr_case_index = 0;
1677 case SCC_PRESIDENT_NAME: {
1679 if (c ==
nullptr)
break;
1691 case SCC_STATION_NAME: {
1695 if (st ==
nullptr) {
1703 static bool use_cache =
true;
1706 builder += st->GetCachedName();
1707 }
else if (!st->name.empty()) {
1711 StringID string_id = st->string_id;
1712 if (st->indtype != IT_INVALID) {
1724 auto tmp_params =
MakeParameters(STR_TOWN_NAME, st->town->index, st->index);
1730 case SCC_TOWN_NAME: {
1732 if (t ==
nullptr)
break;
1734 static bool use_cache =
true;
1737 builder += t->GetCachedName();
1738 }
else if (!t->
name.empty()) {
1742 GetTownName(builder, t);
1747 case SCC_WAYPOINT_NAME: {
1749 if (wp ==
nullptr)
break;
1751 if (!wp->
name.empty()) {
1756 StringID string_id = ((wp->
string_id == STR_SV_STNAME_BUOY) ? STR_FORMAT_BUOY_NAME : STR_FORMAT_WAYPOINT_NAME);
1757 if (wp->
town_cn != 0) string_id++;
1763 case SCC_VEHICLE_NAME: {
1765 if (v ==
nullptr)
break;
1767 if (!v->
name.empty()) {
1779 default: string_id = STR_INVALID_VEHICLE;
break;
1780 case VEH_TRAIN: string_id = STR_SV_TRAIN_NAME;
break;
1781 case VEH_ROAD: string_id = STR_SV_ROAD_VEHICLE_NAME;
break;
1782 case VEH_SHIP: string_id = STR_SV_SHIP_NAME;
break;
1783 case VEH_AIRCRAFT: string_id = STR_SV_AIRCRAFT_NAME;
break;
1791 case SCC_SIGN_NAME: {
1793 if (si ==
nullptr)
break;
1795 if (!si->name.empty()) {
1804 case SCC_STATION_FEATURES: {
1819 }
catch (std::out_of_range &e) {
1820 Debug(misc, 0,
"FormatString: {}", e.what());
1821 builder +=
"(invalid parameter)";
1836static const char *
const _silly_company_names[] = {
1838 "Tiny Transport Ltd.",
1840 "Comfy-Coach & Co.",
1841 "Crush & Bump Ltd.",
1842 "Broken & Late Ltd.",
1844 "Supersonic Travel",
1846 "Lightning International",
1847 "Pannik & Loozit Ltd.",
1848 "Inter-City Transport",
1849 "Getout & Pushit Ltd."
1852static const char *
const _surname_list[] = {
1884static const char *
const _silly_surname_list[] = {
1899static const char _initial_name_letters[] = {
1900 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
1901 'K',
'L',
'M',
'N',
'P',
'R',
'S',
'T',
'W',
1904static std::span<const char * const> GetSurnameOptions()
1907 return _surname_list;
1917 auto surname_options = GetSurnameOptions();
1918 return surname_options[surname_options.size() *
GB(seed, 16, 8) >> 8];
1921static void GenAndCoName(
StringBuilder &builder, uint32_t seed)
1924 builder +=
" & Co.";
1927static void GenPresidentName(
StringBuilder &builder, uint32_t seed)
1929 builder.
PutChar(_initial_name_letters[std::size(_initial_name_letters) *
GB(seed, 0, 8) >> 8]);
1933 size_t index = (std::size(_initial_name_letters) + 35) *
GB(seed, 8, 8) >> 8;
1934 if (index < std::size(_initial_name_letters)) {
1935 builder.
PutChar(_initial_name_letters[index]);
1946 builder += _silly_company_names[std::min<size_t>(args.
GetNextParameter<uint16_t>(), std::size(_silly_company_names) - 1)];
1961 builder +=
" Transport";
1975 this->
version == TO_LE32(LANGUAGE_PACK_VERSION) &&
1995 return 4 * this->
missing < LANGUAGE_TOTAL_STRINGS;
2006 size_t total_len = 0;
2008 if (!lang_pack)
return false;
2011 const char *end = (
char *)lang_pack.get() + total_len + 1;
2014 if (end <= lang_pack->data || !lang_pack->IsValid()) {
2018 std::array<uint, TEXT_TAB_END> tab_start, tab_num;
2022 uint16_t num = FROM_LE16(lang_pack->offsets[i]);
2025 tab_start[i] = count;
2031 std::vector<std::string_view> strings;
2034 char *s = lang_pack->data;
2035 for (uint i = 0; i < count; i++) {
2036 size_t len =
static_cast<uint8_t
>(*s++);
2037 if (s + len >= end)
return false;
2040 len = ((len & 0x3F) << 8) +
static_cast<uint8_t
>(*s++);
2041 if (s + len >= end)
return false;
2043 strings.emplace_back(s, len);
2046 assert(strings.size() == count);
2048 _langpack.langpack = std::move(lang_pack);
2049 _langpack.strings = std::move(strings);
2060 extern void Win32SetCurrentLocaleName(std::string iso_code);
2071 UErrorCode status = U_ZERO_ERROR;
2076 if (U_FAILURE(status)) {
2102#if !(defined(_WIN32) || defined(__APPLE__))
2115 env = std::getenv(
"LANGUAGE");
2116 if (env !=
nullptr)
return env;
2118 env = std::getenv(
"LC_ALL");
2119 if (env !=
nullptr)
return env;
2121 if (param !=
nullptr) {
2122 env = std::getenv(param);
2123 if (env !=
nullptr)
return env;
2126 return std::getenv(
"LANG");
2140 if (newgrflangid == lang.newgrflangid)
return ⟨
2155 if (!f.has_value())
return false;
2157 size_t read = fread(hdr,
sizeof(*hdr), 1, *f);
2159 bool ret = read == 1 && hdr->
IsValid();
2175 std::error_code error_code;
2176 for (
const auto &dir_entry : std::filesystem::directory_iterator(
OTTD2FS(path), error_code)) {
2177 if (!dir_entry.is_regular_file())
continue;
2178 if (dir_entry.path().extension() !=
".lng")
continue;
2181 lmd.
file = dir_entry.path();
2193 Debug(misc, 9,
"Unable to open directory {}: {}", path, error_code.message());
2206 if (
_languages.empty()) UserError(
"No available language packs (invalid versions?)");
2210 if (lang ==
nullptr) lang =
"en_GB";
2222 chosen_language = &lng;
2226 if (strcmp (lng.isocode,
"en_GB") == 0) en_GB_fallback = &lng;
2229 if (!lng.IsReasonablyFinished())
continue;
2231 if (strncmp(lng.isocode, lang, 5) == 0) chosen_language = &lng;
2232 if (strncmp(lng.isocode, lang, 2) == 0) language_fallback = &lng;
2237 if (chosen_language ==
nullptr) {
2238 chosen_language = (language_fallback !=
nullptr) ? language_fallback : en_GB_fallback;
2250 return _langpack.langpack->isocode;
2265 for (
char32_t c :
Utf8View(*text)) {
2266 if (c >= SCC_FIRST_FONT && c <= SCC_LAST_FONT) {
2267 size = (
FontSize)(c - SCC_FIRST_FONT);
2271 std::string size_name;
2274 case FS_NORMAL: size_name =
"medium";
break;
2275 case FS_SMALL: size_name =
"small";
break;
2276 case FS_LARGE: size_name =
"large";
break;
2277 case FS_MONO: size_name =
"mono";
break;
2278 default: NOT_REACHED();
2281 Debug(fontcache, 0,
"Font is missing glyphs to display char 0x{:X} in {} font size", (
int)c, size_name);
2309 std::string_view ret = _langpack.strings[_langpack.
langtab_start[this->
i] + this->
j];
2312 while (this->i < TEXT_TAB_END && this->
j >= _langpack.
langtab_num[this->i]) {
2327#if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA)
2332 settings->small.os_handle = os_data;
2333 settings->medium.os_handle = os_data;
2334 settings->large.os_handle = os_data;
2355 if (searcher ==
nullptr) searcher = &pack_searcher;
2357#if defined(WITH_FREETYPE) || defined(_WIN32) || defined(WITH_COCOA)
2361 bool any_font_configured = !_fcsettings.
medium.
font.empty();
2367 bad_font = !
SetFallbackFont(&_fcsettings, _langpack.langpack->isocode, searcher);
2369 _fcsettings = std::move(backup);
2371 if (!bad_font && any_font_configured) {
2375 std::string err_str;
2378 builder.
Put(
"The current font is missing some of the characters used in the texts for this language. Using system fallback font instead.");
2382 if (bad_font && base_font) {
2396 std::string err_str;
2399 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.");
2410#if !(defined(WITH_ICU_I18N) && defined(WITH_HARFBUZZ)) && !defined(WITH_UNISCRIBE) && !defined(WITH_COCOA)
2421 std::string err_str;
2424 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.
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
debug_inline static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
uint8_t CargoType
Cargo slots to indicate a cargo type within a game.
bool IsValidCargoType(CargoType cargo)
Test whether cargo type is not INVALID_CARGO.
std::vector< const CargoSpec * > _sorted_cargo_specs
Cargo specifications sorted alphabetically by name.
void InitializeSortedCargoSpecs()
Initialize the list of sorted cargo specifications.
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.
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.
static std::optional< FileHandle > Open(const std::string &filename, const std::string &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 FontCache * Get(FontSize fs)
Get the font cache of a given font size.
Helper for searching through the language pack.
bool Monospace() override
Whether to search for a monospace font or not.
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.
void SetFontNames(FontCacheSettings *settings, const char *font_name, const void *os_data) override
Set the right font names.
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.
virtual void Reset()=0
Reset the search, i.e.
virtual FontSize DefaultSize()=0
Get the default (font) size of the string.
bool FindMissingGlyphs()
Check whether there are glyphs missing in the current language.
virtual bool Monospace()=0
Whether to search for a monospace font or not.
virtual std::optional< std::string_view > NextString()=0
Get the next string to search through.
Compose data into a growing std::string.
back_insert_iterator back_inserter()
Create a back-insert-iterator.
void SetOffset(size_t offset)
Set the offset within the string from where to return the next result of GetInt64 or GetInt32.
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...
const char * GetNextParameterString()
Get the next string parameter from our parameters.
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.
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.
std::pair< size_t, char32_t > DecodeUtf8(std::string_view buf)
Decode a character from UTF-8.
Functions to handle different currencies.
const CurrencySpec & GetCurrency()
Get the currently selected currency.
Functions related to debugging.
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Base for all depots (except hangars)
Function to handling different endian machines.
Functions related to errors.
@ WL_WARNING
Other information.
@ WL_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_DIR
Subdirectory for all translation files.
fluid_settings_t * settings
FluidSynth settings handle.
void InitFontCache(bool monospace)
(Re)initialize the font cache related things, i.e.
Functions related to detecting/finding the right font.
bool SetFallbackFont(struct FontCacheSettings *settings, const std::string &language_isocode, class MissingGlyphSearcher *callback)
We would like to have a fallback font as the current one doesn't contain all characters we need.
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(bool monospace)
Initialize _stringwidth_table cache.
Functions related to laying out the texts.
FontSize
Available font sizes.
@ FS_MONO
Index of the monospaced font in the font tables.
@ FS_SMALL
Index of the small font in the font tables.
@ FS_NORMAL
Index of the normal font in the font tables.
@ FS_LARGE
Index of the large font in the font tables.
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.
Information about languages and their files.
static const uint8_t MAX_NUM_GENDERS
Maximum number of supported genders.
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.
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
uint16_t GetVehicleCallback(CallbackID callback, uint32_t param1, uint32_t param2, EngineID engine, const Vehicle *v)
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.
void SetCurrentGrfLangID(uint8_t language_id)
Equivalence Setter function between game and newgrf langID.
char32_t RemapNewGRFStringControlCode(char32_t scc, const char **str)
Emit OpenTTD's internal string code for the different NewGRF string codes.
std::string GetGRFStringWithTextStack(const struct GRFFile *grffile, GRFStringID grfstringid, uint8_t num_entries)
Format a GRF string using the text ref stack for parameters.
Header of Action 04 "universal holder" structure and functions.
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.
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.
Definition of base types and functions in a cross-platform compatible way.
#define lengthof(array)
Return the length of an fixed size array.
bool StrValid(std::span< const char > str)
Checks whether the given string is valid, i.e.
size_t Utf8Decode(char32_t *c, const char *s)
Decode and consume the next UTF-8 encoded character.
Functions related to low-level strings.
bool StrEmpty(const char *s)
Check if a string buffer is empty.
bool IsTextDirectionChar(char32_t c)
Is the given character a text direction character.
void MacOSSetCurrentLocaleName(const char *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.
LanguageList _languages
The actual list of language meta data.
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::string_view GetListSeparator()
Get the list separator string for the current language.
static const Units _units_height[]
Unit conversions for height.
const LanguageMetadata * _current_language
The currently loaded language.
static void FormatBytes(StringBuilder &builder, int64_t number)
Format a given number as a number of bytes with the SI prefix.
const char * GetCurrentLanguageIsoCode()
Get the ISO language code of the currently loaded language.
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.
void CheckForMissingGlyphs(bool base_font, MissingGlyphSearcher *searcher)
Check whether the currently loaded language pack uses characters that the currently loaded font does ...
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.
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 void FormatNumber(StringBuilder &builder, int64_t number, const char *separator)
Format a number into a string.
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
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 const UnitsLong _units_weight[]
Unit conversions for weight.
static const Units _units_velocity_calendar[]
Unit conversions for velocity.
std::unique_ptr< icu::Collator > _current_collator
Collator for the language currently in use.
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 const char * GetSurname(uint32_t seed)
Get the surname of the president with the given seed.
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 const char * DecodeEncodedString(const char *str, bool game_script, StringBuilder &builder)
Decodes an encoded string during FormatString.
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.
const char * GetCurrentLocale(const char *param)
Determine the current charset based on the environment First check some default values,...
uint64_t GetParamMaxDigits(uint count, FontSize size)
Get some number that is suitable for string size computations.
static const Units _units_time_years_or_periods[]
Unit conversions for time in calendar years or economic periods.
static int DeterminePluralForm(int64_t count, int plural_form)
Determine the "plural" index given a plural form and a number.
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.
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.
StringID quantifier
Text for multiple units of cargo of this 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.
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.
uint8_t symbol_pos
The currency symbol is represented by two possible values, prefix and suffix Usage of one or the othe...
uint16_t town_cn
The N-1th depot for this town (consecutive number)
Settings for the four different fonts.
FontCacheSubSetting mono
The mono space font used for license/readme viewers.
FontCacheSubSetting medium
The normal font size.
std::string font
The name of the font, or path to the font.
const void * os_handle
Optional native OS font info. Only valid during font search.
Dynamic data of a loaded NewGRF.
LandscapeType landscape
the landscape we're currently in
LocaleSettings locale
settings related to used currency/unit system in the current game
GameCreationSettings game_creation
settings used during the creation of a game (map)
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.
std::string list_separator
Current list separator 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.
uint8_t units_velocity_nautical
unit system for velocity of ships and aircraft
uint8_t units_velocity
unit system for velocity of trains and road vehicles
std::string digit_decimal_separator
decimal separator
std::string digit_group_separator_currency
thousand separator for currencies
uint8_t units_power
unit system for power
uint8_t units_height
unit system for height
uint8_t units_force
unit system for force
uint8_t units_volume
unit system for volume
uint8_t units_weight
unit system for weight
std::string digit_group_separator
thousand separator for non-currencies
static Titem * Get(auto index)
Returns Titem with given index.
Tindex index
Index of this pool item.
static Titem * GetIfValid(auto index)
Returns Titem with given index.
static Station * GetIfValid(auto index)
Returns station if the index is a valid index for this station type.
The data required to format and validate a single parameter of a string.
Templated helper to make a type-safe 'typedef' representing a single POD value.
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.
Handling of UTF-8 encoded data.
Base class for all vehicles.
VehicleType
Available vehicle types.
@ VEH_ROAD
Road vehicle type.
@ VEH_AIRCRAFT
Aircraft vehicle type.
@ VEH_SHIP
Ship vehicle type.
@ VEH_TRAIN
Train vehicle type.
std::wstring OTTD2FS(const std::string &name)
Convert from OpenTTD's encoding to a wide string.
std::string FS2OTTD(const std::wstring &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.
@ WC_STATION_LIST
Station list; Window numbers:
@ WC_ROADVEH_LIST
Road vehicle list; Window numbers:
@ WC_INDUSTRY_DIRECTORY
Industry directory; Window numbers:
@ WC_SHIPS_LIST
Ships list; Window numbers:
@ WC_TRAINS_LIST
Trains list; Window numbers:
@ WC_BUILD_VEHICLE
Build vehicle; Window numbers:
@ WC_AIRCRAFT_LIST
Aircraft list; Window numbers: