43 #include "table/strings.h" 65 assert(this->
type != NULL);
77 DEBUG(misc, 0,
"Trying to read invalid string parameter");
80 if (this->type != NULL) {
81 if (this->type[this->
offset] != 0 && this->type[this->
offset] != type) {
82 DEBUG(misc, 0,
"Trying to read string parameter with wrong type");
111 while (max_value >= 10) {
128 uint64 val = count > 1 ? front : next;
129 for (; count > 1; count--) {
130 val = 10 * val + next;
168 GetString(buf,
string,
lastof(buf));
171 for (
int i = 0; i < num; i++) {
173 strings[i] =
stredup((
const char *)(
size_t)_global_string_params.GetParam(i));
174 dst[i] = (size_t)strings[i];
181 static char *StationGetSpecialString(
char *buff,
int x,
const char *last);
182 static char *GetSpecialTownNameString(
char *buff,
int ind, uint32 seed,
const char *last);
183 static char *GetSpecialNameString(
char *buff,
int ind,
StringParameters *args,
const char *last);
185 static char *
FormatString(
char *buff,
const char *str,
StringParameters *args,
const char *last, uint case_index = 0,
bool game_script =
false,
bool dry_run =
false);
191 static char **_langpack_offs;
198 const char *GetStringPtr(
StringID string)
203 case TEXT_TAB_OLD_NEWGRF: NOT_REACHED();
228 if (index >= 0xC0 && !game_script) {
229 return GetSpecialTownNameString(buffr, index - 0xC0, args->
GetInt32(), last);
233 case TEXT_TAB_SPECIAL:
234 if (index >= 0xE4 && !game_script) {
235 return GetSpecialNameString(buffr, index - 0xE4, args, last);
239 case TEXT_TAB_OLD_CUSTOM:
242 error(
"Incorrect conversion of custom name string.");
249 case TEXT_TAB_OLD_NEWGRF:
263 error(
"String 0x%X is invalid. You are probably using an old version of the .lng file.\n",
string);
266 return FormatString(buffr, GetStringPtr(
string), args, last, case_index);
269 char *GetString(
char *buffr,
StringID string,
const char *last)
272 _global_string_params.
offset = 0;
307 static char *
FormatNumber(
char *buff, int64 number,
const char *last,
const char *separator,
int zerofill = 1,
int fractional_digits = 0)
309 static const int max_digits = 20;
310 uint64 divisor = 10000000000000000000ULL;
311 zerofill += fractional_digits;
312 int thousands_offset = (max_digits - fractional_digits - 1) % 3;
321 for (
int i = 0; i < max_digits; i++) {
322 if (i == max_digits - fractional_digits) {
325 buff +=
seprintf(buff, last,
"%s", decimal_separator);
329 if (num >= divisor) {
330 quot = num / divisor;
333 if ((tot |= quot) || i >= max_digits - zerofill) {
334 buff +=
seprintf(buff, last,
"%i", (
int)quot);
335 if ((i % 3) == thousands_offset && i < max_digits - 1 - fractional_digits) buff =
strecpy(buff, separator, last);
346 static char *FormatCommaNumber(
char *buff, int64 number,
const char *last,
int fractional_digits = 0)
350 return FormatNumber(buff, number, last, separator, 1, fractional_digits);
353 static char *FormatNoCommaNumber(
char *buff, int64 number,
const char *last)
358 static char *FormatZerofillNumber(
char *buff, int64 number, int64 count,
const char *last)
363 static char *FormatHexNumber(
char *buff, uint64 number,
const char *last)
365 return buff +
seprintf(buff, last,
"0x" OTTD_PRINTFHEX64, number);
375 static char *
FormatBytes(
char *buff, int64 number,
const char *last)
380 const char *
const iec_prefixes[] = {
"",
"Ki",
"Mi",
"Gi",
"Ti",
"Pi",
"Ei"};
382 while (number >= 1024 * 1024) {
392 buff +=
seprintf(buff, last,
"%i", (
int)number);
393 }
else if (number < 1024 * 10) {
394 buff +=
seprintf(buff, last,
"%i%s%02i", (
int)number / 1024, decimal_separator, (
int)(number % 1024) * 100 / 1024);
395 }
else if (number < 1024 * 100) {
396 buff +=
seprintf(buff, last,
"%i%s%01i", (
int)number / 1024, decimal_separator, (
int)(number % 1024) * 10 / 1024);
398 assert(number < 1024 * 1024);
399 buff +=
seprintf(buff, last,
"%i", (
int)number / 1024);
402 assert(
id <
lengthof(iec_prefixes));
403 buff +=
seprintf(buff, last,
NBSP "%sB", iec_prefixes[
id]);
408 static char *FormatYmdString(
char *buff,
Date date,
const char *last, uint case_index)
413 int64 args[] = {ymd.
day + STR_DAY_NUMBER_1ST - 1, STR_MONTH_ABBREV_JAN + ymd.
month, ymd.
year};
415 return FormatString(buff, GetStringPtr(STR_FORMAT_DATE_LONG), &tmp_params, last, case_index);
418 static char *FormatMonthAndYear(
char *buff,
Date date,
const char *last, uint case_index)
423 int64 args[] = {STR_MONTH_JAN + ymd.
month, ymd.
year};
425 return FormatString(buff, GetStringPtr(STR_FORMAT_DATE_SHORT), &tmp_params, last, case_index);
428 static char *FormatTinyOrISODate(
char *buff,
Date date,
StringID str,
const char *last)
439 int64 args[] = {(int64)(
size_t)day, (int64)(
size_t)month, ymd.
year};
441 return FormatString(buff, GetStringPtr(str), &tmp_params, last);
444 static char *FormatGenericCurrency(
char *buff,
const CurrencySpec *spec,
Money number,
bool compact,
const char *last)
448 bool negative = number < 0;
449 const char *multiplier =
"";
451 number *= spec->rate;
455 if (buff +
Utf8CharLen(SCC_PUSH_COLOUR) > last)
return buff;
457 if (buff +
Utf8CharLen(SCC_RED) > last)
return buff;
459 buff =
strecpy(buff,
"-", last);
472 if (number >= 1000000000 - 500) {
473 number = (number + 500000) / 1000000;
474 multiplier =
NBSP "M";
475 }
else if (number >= 1000000) {
476 number = (number + 500) / 1000;
477 multiplier =
NBSP "k";
482 if (separator == NULL && !
StrEmpty(_currency->separator)) separator = _currency->separator;
485 buff =
strecpy(buff, multiplier, last);
493 if (buff +
Utf8CharLen(SCC_POP_COLOUR) > last)
return buff;
510 uint64 n =
abs(count);
512 switch (plural_form) {
521 return n != 1 ? 1 : 0;
533 return n > 1 ? 1 : 0;
540 return n % 10 == 1 && n % 100 != 11 ? 0 : n != 0 ? 1 : 2;
546 return n == 1 ? 0 : n == 2 ? 1 : n < 7 ? 2 : n < 11 ? 3 : 4;
552 return n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
558 return n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
564 return n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
570 return n % 100 == 1 ? 0 : n % 100 == 2 ? 1 : n % 100 == 3 || n % 100 == 4 ? 2 : 3;
576 return n % 10 == 1 && n % 100 != 11 ? 0 : 1;
582 return n == 1 ? 0 : n >= 2 && n <= 4 ? 1 : 2;
613 return (n == 1 ? 0 : n == 0 || (n % 100 > 1 && n % 100 < 11) ? 1 : (n % 100 > 10 && n % 100 < 20) ? 2 : 3);
618 return ((n == 1 || n == 11) ? 0 : (n == 2 || n == 12) ? 1 : ((n > 2 && n < 11) || (n > 12 && n < 20)) ? 2 : 3);
622 static const char *ParseStringChoice(
const char *b, uint form,
char **dst,
const char *last)
626 uint pos, i, mypos = 0;
628 for (i = pos = 0; i != n; i++) {
629 uint len = (byte)*b++;
630 if (i == form) mypos = pos;
634 *dst +=
seprintf(*dst, last,
"%s", b + mypos);
651 return ((input * this->multiplier) + (round && this->shift != 0 ? 1 << (this->shift - 1) : 0)) >> this->shift;
661 int64
FromDisplay(int64 input,
bool round =
true, int64 divider = 1)
const 663 return ((input << this->shift) + (round ? (this->multiplier * divider) - 1 : 0)) / (this->multiplier * divider);
682 { { 1, 0}, STR_UNITS_VELOCITY_IMPERIAL },
683 { { 103, 6}, STR_UNITS_VELOCITY_METRIC },
684 { {1831, 12}, STR_UNITS_VELOCITY_SI },
689 { { 1, 0}, STR_UNITS_POWER_IMPERIAL },
690 { {4153, 12}, STR_UNITS_POWER_METRIC },
691 { {6109, 13}, STR_UNITS_POWER_SI },
696 { {4515, 12}, STR_UNITS_WEIGHT_SHORT_IMPERIAL, STR_UNITS_WEIGHT_LONG_IMPERIAL },
697 { { 1, 0}, STR_UNITS_WEIGHT_SHORT_METRIC, STR_UNITS_WEIGHT_LONG_METRIC },
698 { {1000, 0}, STR_UNITS_WEIGHT_SHORT_SI, STR_UNITS_WEIGHT_LONG_SI },
703 { {4227, 4}, STR_UNITS_VOLUME_SHORT_IMPERIAL, STR_UNITS_VOLUME_LONG_IMPERIAL },
704 { {1000, 0}, STR_UNITS_VOLUME_SHORT_METRIC, STR_UNITS_VOLUME_LONG_METRIC },
705 { { 1, 0}, STR_UNITS_VOLUME_SHORT_SI, STR_UNITS_VOLUME_LONG_SI },
710 { {3597, 4}, STR_UNITS_FORCE_IMPERIAL },
711 { {3263, 5}, STR_UNITS_FORCE_METRIC },
712 { { 1, 0}, STR_UNITS_FORCE_SI },
717 { { 3, 0}, STR_UNITS_HEIGHT_IMPERIAL },
718 { { 1, 0}, STR_UNITS_HEIGHT_METRIC },
719 { { 1, 0}, STR_UNITS_HEIGHT_SI },
774 uint orig_offset = args->
offset;
786 FormatString(buff, str_arg, args, last, case_index, game_script,
true);
789 FormatString(buff, str_arg, args, last, case_index, game_script,
true);
792 args->
offset = orig_offset;
795 uint next_substr_case_index = 0;
796 char *buf_start = buff;
797 std::stack<const char *, std::vector<const char *>> str_stack;
798 str_stack.push(str_arg);
801 while (!str_stack.empty() && (b = Utf8Consume(&str_stack.top())) ==
'\0') {
804 if (str_stack.empty())
break;
805 const char *&str = str_stack.top();
811 if (b == 0)
continue;
816 uint64 sub_args_data[20];
817 WChar sub_args_type[20];
818 bool sub_args_need_free[20];
822 memset(sub_args_need_free, 0,
sizeof(sub_args_need_free));
825 uint32 stringid = strtoul(str, &p, 16);
826 if (*p !=
':' && *p !=
'\0') {
827 while (*p !=
'\0') p++;
829 buff =
strecat(buff,
"(invalid SCC_ENCODED)", last);
833 while (*p !=
'\0') p++;
835 buff =
strecat(buff,
"(invalid StringID)", last);
840 while (*p !=
'\0' && i < 20) {
845 bool instring =
false;
852 if (*p ==
'"' && escape) {
859 instring = !instring;
866 if (*p ==
':')
break;
867 if (*p ==
'\0')
break;
874 bool lookup = (l == SCC_ENCODED);
875 if (lookup) s += len;
877 param = strtoull(s, &p, 16);
881 while (*p !=
'\0') p++;
883 buff =
strecat(buff,
"(invalid sub-StringID)", last);
889 sub_args.SetParam(i++, param);
894 sub_args_need_free[i] =
true;
895 sub_args.SetParam(i++, (uint64)(
size_t)g);
904 for (
int i = 0; i < 20; i++) {
905 if (sub_args_need_free[i])
free((
void *)sub_args.GetParam(i));
911 StringID substr = Utf8Consume(&str);
912 str_stack.push(GetStringPtr(substr));
918 str_stack.push(GetStringPtr(substr));
919 case_index = next_substr_case_index;
920 next_substr_case_index = 0;
925 case SCC_GENDER_LIST: {
927 uint
offset = orig_offset + (byte)*str++;
948 WChar c = Utf8Consume(&s);
950 if (c == SCC_GENDER_INDEX) gender = (byte)s[0];
952 str = ParseStringChoice(str, gender, &buff, last);
958 case SCC_GENDER_INDEX:
967 case SCC_PLURAL_LIST: {
968 int plural_form = *str++;
969 uint
offset = orig_offset + (byte)*str++;
975 case SCC_ARG_INDEX: {
976 args->
offset = orig_offset + (byte)*str++;
983 next_substr_case_index = (byte)*str++;
987 case SCC_SWITCH_CASE: {
990 uint num = (byte)*str++;
992 if ((byte)str[0] == case_index) {
998 str += 3 + (str[1] << 8) + str[2];
1005 buff =
strecpy(buff, _openttd_revision, last);
1008 case SCC_RAW_STRING_POINTER: {
1009 if (game_script)
break;
1010 const char *str = (
const char *)(
size_t)args->
GetInt64(SCC_RAW_STRING_POINTER);
1022 buff =
GetStringWithArgs(buff, str, &tmp_params, last, next_substr_case_index, game_script);
1023 next_substr_case_index = 0;
1037 uint size = b - SCC_STRING1 + 1;
1039 buff =
strecat(buff,
"(too many parameters)", last);
1042 buff =
GetStringWithArgs(buff, str, &sub_args, last, next_substr_case_index, game_script);
1044 next_substr_case_index = 0;
1049 buff = FormatCommaNumber(buff, args->
GetInt64(SCC_COMMA), last);
1053 int64 number = args->
GetInt64(SCC_DECIMAL);
1054 int digits = args->
GetInt32(SCC_DECIMAL);
1055 buff = FormatCommaNumber(buff, number, last, digits);
1060 buff = FormatNoCommaNumber(buff, args->
GetInt64(SCC_NUM), last);
1063 case SCC_ZEROFILL_NUM: {
1065 buff = FormatZerofillNumber(buff, num, args->
GetInt64(), last);
1070 buff = FormatHexNumber(buff, (uint64)args->
GetInt64(SCC_HEX), last);
1077 case SCC_CARGO_TINY: {
1086 switch (cargo_str) {
1101 buff = FormatCommaNumber(buff, amount, last);
1105 case SCC_CARGO_SHORT: {
1113 switch (cargo_str) {
1139 case SCC_CARGO_LONG: {
1150 case SCC_CARGO_LIST: {
1151 CargoTypes cmask = args->
GetInt64(SCC_CARGO_LIST);
1158 if (buff >= last - 2)
break;
1172 if (first) buff =
GetStringWithArgs(buff, STR_JUST_NOTHING, args, last, next_substr_case_index, game_script);
1175 next_substr_case_index = 0;
1178 assert(buff < last);
1182 case SCC_CURRENCY_SHORT:
1183 buff = FormatGenericCurrency(buff, _currency, args->
GetInt64(),
true, last);
1186 case SCC_CURRENCY_LONG:
1187 buff = FormatGenericCurrency(buff, _currency, args->
GetInt64(SCC_CURRENCY_LONG),
false, last);
1191 buff = FormatTinyOrISODate(buff, args->
GetInt32(SCC_DATE_TINY), STR_FORMAT_DATE_TINY, last);
1194 case SCC_DATE_SHORT:
1195 buff = FormatMonthAndYear(buff, args->
GetInt32(SCC_DATE_SHORT), last, next_substr_case_index);
1196 next_substr_case_index = 0;
1200 buff = FormatYmdString(buff, args->
GetInt32(SCC_DATE_LONG), last, next_substr_case_index);
1201 next_substr_case_index = 0;
1205 buff = FormatTinyOrISODate(buff, args->
GetInt32(), STR_FORMAT_DATE_ISO, last);
1232 case SCC_VELOCITY: {
1240 case SCC_VOLUME_SHORT: {
1248 case SCC_VOLUME_LONG: {
1256 case SCC_WEIGHT_SHORT: {
1264 case SCC_WEIGHT_LONG: {
1272 case SCC_COMPANY_NAME: {
1274 if (c == NULL)
break;
1276 if (c->
name != NULL) {
1277 int64 args_array[] = {(int64)(
size_t)c->
name};
1281 int64 args_array[] = {c->
name_2};
1288 case SCC_COMPANY_NUM: {
1293 int64 args_array[] = {company + 1};
1300 case SCC_DEPOT_NAME: {
1303 uint64 args_array[] = {(uint64)args->
GetInt32()};
1304 WChar types_array[] = {SCC_STATION_NAME};
1306 buff =
GetStringWithArgs(buff, STR_FORMAT_DEPOT_NAME_AIRCRAFT, &tmp_params, last);
1311 if (d->name != NULL) {
1312 int64 args_array[] = {(int64)(
size_t)d->name};
1318 buff =
GetStringWithArgs(buff, STR_FORMAT_DEPOT_NAME_TRAIN + 2 * vt + (d->
town_cn == 0 ? 0 : 1), &tmp_params, last);
1323 case SCC_ENGINE_NAME: {
1325 if (e == NULL)
break;
1328 int64 args_array[] = {(int64)(
size_t)e->
name};
1338 case SCC_GROUP_NAME: {
1340 if (g == NULL)
break;
1342 if (g->
name != NULL) {
1343 int64 args_array[] = {(int64)(
size_t)g->
name};
1347 int64 args_array[] = {g->
index};
1355 case SCC_INDUSTRY_NAME: {
1357 if (i == NULL)
break;
1369 buff =
FormatString(buff, GetStringPtr(STR_FORMAT_INDUSTRY_NAME), &tmp_params, last, next_substr_case_index);
1371 next_substr_case_index = 0;
1375 case SCC_PRESIDENT_NAME: {
1377 if (c == NULL)
break;
1391 case SCC_STATION_NAME: {
1392 StationID sid = args->
GetInt32(SCC_STATION_NAME);
1404 if (st->
name != NULL) {
1405 int64 args_array[] = {(int64)(
size_t)st->
name};
1410 if (st->
indtype != IT_INVALID) {
1422 uint64 args_array[] = {STR_TOWN_NAME, st->
town->
index, st->
index};
1423 WChar types_array[] = {0, SCC_TOWN_NAME, SCC_NUM};
1430 case SCC_TOWN_NAME: {
1432 if (t == NULL)
break;
1434 if (t->
name != NULL) {
1435 int64 args_array[] = {(int64)(
size_t)t->
name};
1444 case SCC_WAYPOINT_NAME: {
1446 if (wp == NULL)
break;
1448 if (wp->
name != NULL) {
1449 int64 args_array[] = {(int64)(
size_t)wp->
name};
1455 StringID str = ((wp->
string_id == STR_SV_STNAME_BUOY) ? STR_FORMAT_BUOY_NAME : STR_FORMAT_WAYPOINT_NAME);
1462 case SCC_VEHICLE_NAME: {
1464 if (v == NULL)
break;
1466 if (v->
name != NULL) {
1467 int64 args_array[] = {(int64)(
size_t)v->
name};
1476 default: str = STR_INVALID_VEHICLE;
break;
1477 case VEH_TRAIN: str = STR_SV_TRAIN_NAME;
break;
1478 case VEH_ROAD: str = STR_SV_ROAD_VEHICLE_NAME;
break;
1479 case VEH_SHIP: str = STR_SV_SHIP_NAME;
break;
1488 case SCC_SIGN_NAME: {
1490 if (si == NULL)
break;
1492 if (si->name != NULL) {
1493 int64 args_array[] = {(int64)(
size_t)si->name};
1503 case SCC_STATION_FEATURES: {
1504 buff = StationGetSpecialString(buff, args->
GetInt32(SCC_STATION_FEATURES), last);
1518 static char *StationGetSpecialString(
char *buff,
int x,
const char *last)
1529 static char *GetSpecialTownNameString(
char *buff,
int ind, uint32 seed,
const char *last)
1534 static const char *
const _silly_company_names[] = {
1536 "Tiny Transport Ltd.",
1538 "Comfy-Coach & Co.",
1539 "Crush & Bump Ltd.",
1540 "Broken & Late Ltd.",
1542 "Supersonic Travel",
1544 "Lightning International",
1545 "Pannik & Loozit Ltd.",
1546 "Inter-City Transport",
1547 "Getout & Pushit Ltd." 1550 static const char *
const _surname_list[] = {
1582 static const char *
const _silly_surname_list[] = {
1597 static const char _initial_name_letters[] = {
1598 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
1599 'K',
'L',
'M',
'N',
'P',
'R',
'S',
'T',
'W',
1602 static char *GenAndCoName(
char *buff, uint32 arg,
const char *last)
1604 const char *
const *base;
1608 base = _silly_surname_list;
1609 num =
lengthof(_silly_surname_list);
1611 base = _surname_list;
1615 buff =
strecpy(buff, base[num *
GB(arg, 16, 8) >> 8], last);
1616 buff =
strecpy(buff,
" & Co.", last);
1621 static char *GenPresidentName(
char *buff, uint32 x,
const char *last)
1623 char initial[] =
"?. ";
1624 const char *
const *base;
1628 initial[0] = _initial_name_letters[
sizeof(_initial_name_letters) *
GB(x, 0, 8) >> 8];
1629 buff =
strecpy(buff, initial, last);
1631 i = (
sizeof(_initial_name_letters) + 35) *
GB(x, 8, 8) >> 8;
1632 if (i <
sizeof(_initial_name_letters)) {
1633 initial[0] = _initial_name_letters[i];
1634 buff =
strecpy(buff, initial, last);
1638 base = _silly_surname_list;
1639 num =
lengthof(_silly_surname_list);
1641 base = _surname_list;
1645 buff =
strecpy(buff, base[num *
GB(x, 16, 8) >> 8], last);
1650 static char *GetSpecialNameString(
char *buff,
int ind,
StringParameters *args,
const char *last)
1657 return GenAndCoName(buff, args->
GetInt32(), last);
1660 return GenPresidentName(buff, args->
GetInt32(), last);
1664 if (
IsInsideMM(ind - 6, 0, SPECSTR_TOWNNAME_LAST - SPECSTR_TOWNNAME_START + 1)) {
1665 buff = GetSpecialTownNameString(buff, ind - 6, args->
GetInt32(), last);
1666 return strecpy(buff,
" Transport", last);
1670 if (
IsInsideMM(ind, (SPECSTR_LANGUAGE_START - 0x70E4), (SPECSTR_LANGUAGE_END - 0x70E4) + 1)) {
1671 int i = ind - (SPECSTR_LANGUAGE_START - 0x70E4);
1673 &_languages[i] == _current_language ? _current_language->
own_name : _languages[i].name, last);
1677 if (
IsInsideMM(ind, (SPECSTR_RESOLUTION_START - 0x70E4), (SPECSTR_RESOLUTION_END - 0x70E4) + 1)) {
1678 int i = ind - (SPECSTR_RESOLUTION_START - 0x70E4);
1688 #ifdef ENABLE_NETWORK 1689 extern void SortNetworkLanguages();
1691 static inline void SortNetworkLanguages() {}
1701 this->version == TO_LE32(LANGUAGE_PACK_VERSION) &&
1702 this->plural_form < LANGUAGE_MAX_PLURAL &&
1703 this->text_dir <= 1 &&
1710 StrValid(this->digit_group_separator,
lastof(this->digit_group_separator)) &&
1711 StrValid(this->digit_group_separator_currency,
lastof(this->digit_group_separator_currency)) &&
1712 StrValid(this->digit_decimal_separator,
lastof(this->digit_decimal_separator));
1725 if (lang_pack == NULL)
return false;
1728 const char *end = (
char *)lang_pack + len + 1;
1731 if (end <= lang_pack->
data || !lang_pack->
IsValid()) {
1736 #if TTD_ENDIAN == TTD_BIG_ENDIAN 1744 uint16 num = lang_pack->
offsets[i];
1756 char **langpack_offs = MallocT<char *>(count);
1759 char *s = lang_pack->data;
1761 for (uint i = 0; i < count; i++) {
1762 if (s + len >= end) {
1764 free(langpack_offs);
1768 len = ((len & 0x3F) << 8) + (byte)*s++;
1769 if (s + len >= end) {
1771 free(langpack_offs);
1775 langpack_offs[i] = s;
1782 _langpack = lang_pack;
1784 free(_langpack_offs);
1785 _langpack_offs = langpack_offs;
1787 _current_language = lang;
1789 const char *c_file = strrchr(_current_language->
file, PATHSEPCHAR) + 1;
1794 extern void Win32SetCurrentLocaleName(
const char *iso_code);
1795 Win32SetCurrentLocaleName(_current_language->
isocode);
1803 #ifdef WITH_ICU_SORT 1811 UErrorCode status = U_ZERO_ERROR;
1816 if (U_FAILURE(status)) {
1827 SortNetworkLanguages();
1828 #ifdef ENABLE_NETWORK 1844 #if !(defined(_WIN32) || defined(__APPLE__)) 1857 env = getenv(
"LANGUAGE");
1858 if (env != NULL)
return env;
1860 env = getenv(
"LC_ALL");
1861 if (env != NULL)
return env;
1863 if (param != NULL) {
1864 env = getenv(param);
1865 if (env != NULL)
return env;
1868 return getenv(
"LANG");
1878 GetString(stra, *a,
lastof(stra));
1879 GetString(strb, *b,
lastof(strb));
1892 if (newgrflangid == lang->newgrflangid)
return lang;
1906 FILE *f = fopen(file,
"rb");
1907 if (f == NULL)
return false;
1909 size_t read = fread(hdr,
sizeof(*hdr), 1, f);
1912 bool ret = read == 1 && hdr->
IsValid();
1930 struct dirent *dirent;
1931 while ((dirent = readdir(dir)) != NULL) {
1932 const char *d_name =
FS2OTTD(dirent->d_name);
1933 const char *extension = strrchr(d_name,
'.');
1936 if (extension == NULL || strcmp(extension,
".lng") != 0)
continue;
1943 DEBUG(misc, 3,
"%s is not a valid language file", lmd.
file);
1945 DEBUG(misc, 3,
"%s's language ID is already known", lmd.
file);
1947 *_languages.
Append() = lmd;
1963 char path[MAX_PATH];
1967 if (_languages.
Length() == 0)
usererror(
"No available language packs (invalid versions?)");
1971 if (lang == NULL) lang =
"en_GB";
1982 const char *lang_file = strrchr(lng->file, PATHSEPCHAR) + 1;
1984 chosen_language = lng;
1988 if (strcmp (lng->isocode,
"en_GB") == 0) en_GB_fallback = lng;
1989 if (strncmp(lng->isocode, lang, 5) == 0) chosen_language = lng;
1990 if (strncmp(lng->isocode, lang, 2) == 0) language_fallback = lng;
1995 if (chosen_language == NULL) {
1996 chosen_language = (language_fallback != NULL) ? language_fallback : en_GB_fallback;
2020 const Sprite *question_mark[FS_END];
2023 question_mark[size] =
GetGlyph(size,
'?');
2027 for (
const char *text = this->NextString(); text != NULL; text = this->NextString()) {
2028 FontSize size = this->DefaultSize();
2029 if (str != NULL) *str = text;
2030 for (
WChar c = Utf8Consume(&text); c !=
'\0'; c = Utf8Consume(&text)) {
2031 if (c >= SCC_FIRST_FONT && c <= SCC_LAST_FONT) {
2032 size = (
FontSize)(c - SCC_FIRST_FONT);
2062 const char *ret = _langpack_offs[
_langtab_start[this->i] + this->j];
2065 while (this->i < TEXT_TAB_END && this->j >=
_langtab_num[this->i]) {
2080 #ifdef WITH_FREETYPE 2104 if (searcher == NULL) searcher = &pack_searcher;
2106 #ifdef WITH_FREETYPE 2111 memcpy(&backup, &_freetype,
sizeof(backup));
2115 memcpy(&_freetype, &backup,
sizeof(backup));
2117 if (bad_font && base_font) {
2132 static char *err_str =
stredup(
"XXXThe current font is missing some of the characters used in the texts for this language. Read the readme to see how to solve this.");
2145 #if !defined(WITH_ICU_LAYOUT) && !defined(WITH_UNISCRIBE) && !defined(WITH_COCOA) 2160 static char *err_str =
stredup(
"XXXThis version of OpenTTD does not support right-to-left languages. Recompile with icu enabled.");
Helper for unit conversion.
Functions related to OTTD's strings.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition of stuff that is very close to a company, like the company struct itself.
void CheckForMissingGlyphs(bool base_font, MissingGlyphSearcher *searcher)
Check whether the currently loaded language pack uses characters that the currently loaded font does ...
static Titem * GetIfValid(size_t index)
Returns Titem with given index.
int64 FromDisplay(int64 input, bool round=true, int64 divider=1) const
Convert the displayed value back into a value of OpenTTD's internal unit.
static char * FormatBytes(char *buff, int64 number, const char *last)
Format a given number as a number of bytes with the SI prefix.
static char * FormatString(char *buff, const char *str, StringParameters *args, const char *last, 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.
Inline another string at the current position, StringID is encoded in the string. ...
void SortIndustryTypes()
Initialize the list of sorted industry types.
uint16 town_cn
The N-1th waypoint for this town (consecutive number)
static uint GetStringIndex(StringID str)
Extract the StringIndex from a StringID.
char * name
Name of the company if the user changed it.
WChar * type
Array with type information about the data. Can be NULL when no type information is needed...
Control codes that are embedded in the translation strings.
byte landscape
the landscape we're currently in
static char * strecat(char *dst, const char *src, const char *last)
Appends characters from one string to another.
const char * FS2OTTD(const TCHAR *name)
Convert to OpenTTD's encoding from that of the local environment.
bool UsingNewGRFTextStack()
Check whether the NewGRF text stack is in use.
static const Units _units_height[]
Unit conversions for height.
bool IsEnabled() const
Checks whether the engine is a valid (non-articulated part of an) engine.
static Titem * Get(size_t index)
Returns Titem with given index.
void ClearTypeInformation()
Reset the type array.
Functions related to dates.
static bool IsInsideMM(const T x, const uint min, const uint max)
Checks if a value is in an interval.
icu::Collator * _current_collator
Collator for the language currently in use.
byte units_weight
unit system for weight
Functions to handle different currencies.
int CDECL seprintf(char *str, const char *last, const char *format,...)
Safer implementation of snprintf; same as snprintf except:
Functions related to debugging.
uint num_param
Length of the data array.
static uint64 _global_string_params_data[20]
Global array of string parameters. To access, use SetDParam.
static int DeterminePluralForm(int64 count, int plural_form)
Determine the "plural" index given a plural form and a number.
void SetCurrentGrfLangID(byte language_id)
Equivalence Setter function between game and newgrf langID.
Index of the monospaced font in the font tables.
Data structure describing a sprite.
#define FOR_ALL_SEARCHPATHS(sp)
Iterator for all the search paths.
fluid_settings_t * settings
FluidSynth settings handle.
#define FOR_ALL_SORTED_CARGOSPECS(var)
Loop header for iterating over cargoes, sorted by name.
Specification of a cargo type.
static uint _langtab_num[TEXT_TAB_END]
Offset into langpack offs.
void ShiftParameters(uint amount)
Shift all data in the data array by the given amount to make room for some extra parameters.
Build vehicle; Window numbers:
void CopyInDParam(int offs, const uint64 *src, int num)
Copy num string parameters from array src into the global string parameter array. ...
Base for all depots (except hangars)
Functions related to detecting/finding the right font.
uint offset
Current offset in the data/type arrays.
byte units_velocity
unit system for velocity
Defines the internal data of a functional industry.
const T * Begin() const
Get the pointer to the first item (const)
Base functions regarding game texts.
Tindex index
Index of this pool item.
static bool IsTextDirectionChar(WChar c)
Is the given character a text direction character.
char * president_name
Name of the president if the user changed it.
static StringID MakeStringID(StringTab tab, uint index)
Create a StringID.
static const int DRAW_STRING_BUFFER
Size of the buffer used for drawing strings.
bool HasTypeInformation() const
Does this instance store information about the type of the parameters.
virtual bool Monospace()=0
Whether to search for a monospace font or not.
Functions for Standard In/Out file operations.
size_t Utf8Decode(WChar *c, const char *s)
Decode and consume the next UTF-8 encoded character.
FreeTypeSubSetting large
The largest font; mostly used for newspapers.
Representation of a waypoint.
#define lastof(x)
Get the last element of an fixed size array.
Simple vector template class.
Function to handling different endian machines.
StringTab
StringTabs to group StringIDs.
static StringTab GetStringTab(StringID str)
Extract the StringTab from a StringID.
Searchpath
Types of searchpaths OpenTTD might use.
uint32 name_2
Parameter of name_1.
StringID quantifier
Text for multiple units of cargo of this type.
static T max(const T a, const T b)
Returns the maximum of two values.
Information about a specific unit system with a long variant.
byte units_force
unit system for force
Town * town
The town this station is associated with.
byte units_height
unit system for height
The next variables are part of a NewGRF subsystem for creating text strings.
const T * End() const
Get the pointer behind the last valid item (const)
StringID name
Name of this type of cargo.
Industry directory; Window numbers:
static void GetLanguageList(const char *path)
Gets a list of languages from the given directory.
StringID name
Displayed name of the industry.
char * GetStringWithArgs(char *buffr, StringID string, StringParameters *args, const char *last, uint case_index, bool game_script)
Get a parsed string with most special stringcodes replaced by the string parameters.
Settings for the freetype fonts.
static const Units _units_force[]
Unit conversions for force.
static bool IsValidHumanID(size_t index)
Is this company a valid company, not controlled by a NoAI program?
T * Append(uint to_add=1)
Append an item and return it.
void InitFreeType(bool monospace)
(Re)initialize the freetype related things, i.e.
static void MemMoveT(T *destination, const T *source, size_t num=1)
Type-safe version of memmove().
const char * NextString()
Get the next string to search through.
Helper for searching through the language pack.
void BuildContentTypeStringList()
Build array of all strings corresponding to the content types.
uint ConvertDisplaySpeedToSpeed(uint speed)
Convert the given display speed to the (internal) speed.
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...
uint RemapNewGRFStringControlCode(uint scc, char *buf_start, char **buff, const char **str, int64 *argv, uint argv_size, bool modify_argv)
FormatString for NewGRF specific "magic" string control codes.
byte symbol_pos
The currency symbol is represented by two possible values, prefix and suffix Usage of one or the othe...
void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel wl, int x=0, int y=0, const GRFFile *textref_stack_grffile=NULL, uint textref_stack_size=0, const uint32 *textref_stack=NULL)
Display an error message in a window.
static WChar _global_string_params_type[20]
Type of parameters stored in #_global_string_params.
Header of Action 04 "universal holder" structure and functions.
void SetDParamStr(uint n, const char *str)
This function is used to "bind" a C string to a OpenTTD dparam slot.
Functions related to low-level strings.
void Reset()
Reset the search, i.e.
uint ConvertDisplaySpeedToKmhishSpeed(uint speed)
Convert the given display speed to the km/h-ish speed.
uint64 * data
Array with the actual data.
Functions related to errors.
UnitID unitnumber
unit number, for display purposes only
uint Length() const
Get the number of items in the list.
UnitConversion c
Conversion.
VehicleType
Available vehicle types.
81: Read 2 bytes from the stack as String ID
byte units_volume
unit system for volume
void ReconsiderGameScriptLanguage()
Reconsider the game script language, so we use the right one.
A searcher for missing glyphs.
char * GetTownName(char *buff, const TownNameParams *par, uint32 townnameparts, const char *last)
Fills buffer with specified town name.
Station with truck stops.
Subdirectory for all translation files.
const IndustrySpec * GetIndustrySpec(IndustryType thistype)
Accessor for array _industry_specs.
UnitConversion c
Conversion.
Definition of base types and functions in a cross-platform compatible way.
void LoadStringWidthTable(bool monospace)
Initialize _stringwidth_table cache.
static const uint TAB_SIZE
Number of strings per StringTab.
Data structure to convert between Date and triplet (year, month, and day).
void CDECL usererror(const char *s,...)
Error handling for fatal user errors.
A number of safeguards to prevent using unsafe methods.
int64 ToDisplay(int64 input, bool round=true) const
Convert value from OpenTTD's internal unit into the displayed value.
IndustryType type
type of industry.
void CopyOutDParam(uint64 *dst, int offs, int num)
Copy num string parameters from the global string parameter array to the dst array.
void SetFontNames(FreeTypeSettings *settings, const char *font_name)
Set the right font names.
int64 GetInt64(WChar type=0)
Read an int64 from the argument array.
const LanguageMetadata * GetLanguage(byte newgrflangid)
Get the language with the given NewGRF language ID.
static const uint TAB_SIZE_GAMESCRIPT
Number of strings for GameScripts.
Information about languages and their files.
static const UnitsLong _units_weight[]
Unit conversions for weight.
char * stredup(const char *s, const char *last)
Create a duplicate of the given string.
static int8 Utf8CharLen(WChar c)
Return the length of a UTF-8 encoded character.
void SetDParamMaxDigits(uint n, uint count, FontSize size)
Set DParam n to some number that is suitable for string size computations.
LanguageList _languages
The actual list of language meta data.
Road vehicle list; Window numbers:
Defines the data structure for constructing industry.
bool FindMissingGlyphs(const char **str)
Check whether there are glyphs missing in the current language.
static const uint8 MAX_NUM_GENDERS
Maximum number of supported genders.
char * digit_group_separator_currency
thousand separator for currencies
FreeTypeSubSetting medium
The normal font size.
static bool GetLanguageFileHeader(const char *file, LanguagePackHeader *hdr)
Reads the language file header and checks compatibility.
uint GetDataLeft() const
Return the amount of elements which can still be read.
char * digit_decimal_separator
decimal separator
#define lengthof(x)
Return the length of an fixed size array.
static const uint8 MAX_NUM_CASES
Maximum number of supported cases.
static T min(const T a, const T b)
Returns the minimum of two values.
void InitializeLanguagePacks()
Make a list of the available language packs.
char * name
Custom name of engine.
static const Sprite * GetGlyph(FontSize size, WChar key)
Get the Sprite for a glyph.
StringID s
String for the short variant of the unit.
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Text is written left-to-right by default.
uint i
Iterator for the primary language tables.
FontSize DefaultSize()
Get the default (font) size of the string.
Start of GameScript supplied strings.
Information about a specific unit system.
Station list; Window numbers:
static void MemCpyT(T *destination, const T *source, size_t num=1)
Type-safe version of memcpy().
bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback)
We would like to have a fallback font as the current one doesn't contain all characters we need...
#define DEBUG(name, level,...)
Output a line of debugging information.
static const uint MAX_LANG
Maximum number of languages supported by the game, and the NewGRF specs.
Dimension _resolutions[32]
List of resolutions.
uint32 president_name_2
Parameter of president_name_1.
byte units_power
unit system for power
const LanguageMetadata * _current_language
The currently loaded language.
char * name
Name of vehicle.
char font[MAX_PATH]
The name of the font, or path to the font.
static const Units _units_power[]
Unit conversions for velocity.
char _config_language_file[MAX_PATH]
The file (name) stored in the configuration.
static const UnitsLong _units_volume[]
Unit conversions for volume.
User interface for downloading files.
const char * GetCurrentLanguageIsoCode()
Get the ISO language code of the currently loaded language.
uint ConvertKmhishSpeedToDisplaySpeed(uint speed)
Convert the given km/h-ish speed to the display speed.
int shift
Amount to shift upon conversion.
void InjectDParam(uint amount)
Shift the string parameters in the global string parameter array by amount positions, making room at the beginning.
TextDirection
Directions a text can go to.
int strnatcmp(const char *s1, const char *s2, bool ignore_garbage_at_front)
Compares two strings using case insensitive natural sort.
Base class for all vehicles.
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo ID.
Ships list; Window numbers:
StringID s
String for the unit.
StringID name_1
Name of the company if the user did not change it.
WChar GetTypeAtOffset(uint offset) const
Get the type of a specific element.
TextDirection _current_text_dir
Text direction of the currently selected language.
void SetDParamMaxValue(uint n, uint64 max_value, uint min_count, FontSize size)
Set DParam n to some number that is suitable for string size computations.
StringID president_name_1
Name of the president if the user did not change it.
void GetBroadestDigit(uint *front, uint *next, FontSize size)
Determine the broadest digits for guessing the maximum width of a n-digit number. ...
void CDECL error(const char *s,...)
Error handling for fatal non-user errors.
static T abs(const T a)
Returns the absolute value of (scalar) variable.
void InitializeSortedCargoSpecs()
Initialize the list of sorted cargo specifications.
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
StringID string_id
Default name of engine.
Trains list; Window numbers:
FreeTypeSubSetting small
The smallest font; mostly used for zoomed out view.
FontSize
Available font sizes.
void RestoreTextRefStackBackup(struct TextRefStack *backup)
Restore a copy of the text stack to the used stack.
char * strecpy(char *dst, const char *src, const char *last)
Copies characters from one buffer to another.
static DIR * ttd_opendir(const char *path)
A wrapper around opendir() which will convert the string from OPENTTD encoding to that of the filesys...
const char * GetGRFStringPtr(uint16 stringid)
Get a C-string from a stringid set by a newgrf.
int multiplier
Amount to multiply upon conversion.
static bool _scan_for_gender_data
Are we scanning for the gender of the current string? (instead of formatting it)
Index of the normal font in the font tables.
char * digit_group_separator
thousand separator for non-currencies
Start of NewGRF supplied strings.
Station with train station.
LocaleSettings locale
settings related to used currency/unit system in the current game
Aircraft list; Window numbers:
Specification of a currency.
static const Units _units_velocity[]
Unit conversions for velocity.
char * name
Custom town name. If NULL, the town was not renamed and uses the generated name.
uint ConvertSpeedToDisplaySpeed(uint speed)
Convert the given (internal) speed to the display speed.
CargoID Index() const
Determines index of this cargospec.
static size_t GetArraySize()
Total number of cargospecs, both valid and invalid.
struct TextRefStack * CreateTextRefStackBackup()
Create a backup of the current NewGRF text stack.
char * GenerateTownNameString(char *buf, const char *last, size_t lang, uint32 seed)
Generates town name from given seed.
static uint _langtab_start[TEXT_TAB_END]
Offset into langpack offs.
static char * FormatNumber(char *buff, int64 number, const char *last, const char *separator, int zerofill=1, int fractional_digits=0)
Format a number into a string.
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
size_t Utf8Encode(char *buf, WChar c)
Encode a unicode character and place it in the buffer.
int32 Date
The type to store our dates in.
static void free(const void *ptr)
Version of the standard free that accepts const pointers.
declaration of OTTD revision dependent variables
StringID station_name
Default name for nearby station.
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
Town name generator stuff.
StringID units_volume
Name of a single unit of cargo of this type.
bool ReadLanguagePack(const LanguageMetadata *lang)
Read a particular language.
void * ReadFileToMem(const char *filename, size_t *lenp, size_t maxsize)
Load a file into memory.
uint64 * GetPointerToOffset(uint offset) const
Get a pointer to a specific element in the data array.
GameCreationSettings game_creation
settings used during the creation of a game (map)
const char * GetCurrentLocale(const char *param)
Determine the current charset based on the environment First check some default values, after this one we passed ourselves and if none exist return the value for $LANG.
const char * GetGameStringPtr(uint id)
Get the string pointer of a particular game string.
byte CargoID
Cargo slots to indicate a cargo type within a game.
IndustryType indtype
Industry type to get the name from.
Owner
Enum for all companies/owners.
Window functions not directly related to making/drawing windows.
int32 GetInt32(WChar type=0)
Read an int32 from the argument array.
Base classes/functions for stations.
Errors (eg. saving/loading failed)
#define NBSP
A non-breaking space.
uint32 WChar
Type for wide characters, i.e.
void ConvertDateToYMD(Date date, YearMonthDay *ymd)
Converts a Date to a Year, Month & Day.
uint j
Iterator for the secondary language tables.
StringID string_id
Default name (town area) of station.
VehicleTypeByte type
Type of vehicle.
StringID l
String for the long variant of the unit.
void MacOSSetCurrentLocaleName(const char *iso_code)
Store current language locale as a CoreFounation locale.
bool StrValid(const char *str, const char *last)
Checks whether the given string is valid, i.e.
uint16 town_cn
The N-1th depot for this town (consecutive number)
bool Monospace()
Whether to search for a monospace font or not.
static void MemSetT(T *ptr, byte value, size_t num=1)
Type-safe version of memset().
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
uint64 * GetDataPointer() const
Get a pointer to the current element in the data array.
static Station * GetIfValid(size_t index)
Returns station if the index is a valid index for this station type.
void BuildIndustriesLegend()
Fills an array for the industries legends.