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 assert(this->type[this->
offset] == 0 || this->type[this->
offset] == type);
108 while (max_value >= 10) {
125 uint64 val = count > 1 ? front : next;
126 for (; count > 1; count--) {
127 val = 10 * val + next;
165 GetString(buf,
string,
lastof(buf));
168 for (
int i = 0; i < num; i++) {
170 strings[i] =
stredup((
const char *)(
size_t)_global_string_params.GetParam(i));
171 dst[i] = (size_t)strings[i];
178 static char *StationGetSpecialString(
char *buff,
int x,
const char *last);
179 static char *GetSpecialTownNameString(
char *buff,
int ind, uint32 seed,
const char *last);
180 static char *GetSpecialNameString(
char *buff,
int ind,
StringParameters *args,
const char *last);
182 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);
188 static char **_langpack_offs;
195 const char *GetStringPtr(
StringID string)
200 case TEXT_TAB_OLD_NEWGRF: NOT_REACHED();
225 if (index >= 0xC0 && !game_script) {
226 return GetSpecialTownNameString(buffr, index - 0xC0, args->
GetInt32(), last);
230 case TEXT_TAB_SPECIAL:
231 if (index >= 0xE4 && !game_script) {
232 return GetSpecialNameString(buffr, index - 0xE4, args, last);
236 case TEXT_TAB_OLD_CUSTOM:
239 error(
"Incorrect conversion of custom name string.");
246 case TEXT_TAB_OLD_NEWGRF:
260 error(
"String 0x%X is invalid. You are probably using an old version of the .lng file.\n",
string);
263 return FormatString(buffr, GetStringPtr(
string), args, last, case_index);
266 char *GetString(
char *buffr,
StringID string,
const char *last)
269 _global_string_params.
offset = 0;
304 static char *
FormatNumber(
char *buff, int64 number,
const char *last,
const char *separator,
int zerofill = 1,
int fractional_digits = 0)
306 static const int max_digits = 20;
307 uint64 divisor = 10000000000000000000ULL;
308 zerofill += fractional_digits;
309 int thousands_offset = (max_digits - fractional_digits - 1) % 3;
318 for (
int i = 0; i < max_digits; i++) {
319 if (i == max_digits - fractional_digits) {
322 buff +=
seprintf(buff, last,
"%s", decimal_separator);
326 if (num >= divisor) {
327 quot = num / divisor;
330 if ((tot |= quot) || i >= max_digits - zerofill) {
331 buff +=
seprintf(buff, last,
"%i", (
int)quot);
332 if ((i % 3) == thousands_offset && i < max_digits - 1 - fractional_digits) buff =
strecpy(buff, separator, last);
343 static char *FormatCommaNumber(
char *buff, int64 number,
const char *last,
int fractional_digits = 0)
347 return FormatNumber(buff, number, last, separator, 1, fractional_digits);
350 static char *FormatNoCommaNumber(
char *buff, int64 number,
const char *last)
355 static char *FormatZerofillNumber(
char *buff, int64 number, int64 count,
const char *last)
360 static char *FormatHexNumber(
char *buff, uint64 number,
const char *last)
362 return buff +
seprintf(buff, last,
"0x" OTTD_PRINTFHEX64, number);
372 static char *
FormatBytes(
char *buff, int64 number,
const char *last)
377 const char *
const iec_prefixes[] = {
"",
"Ki",
"Mi",
"Gi",
"Ti",
"Pi",
"Ei"};
379 while (number >= 1024 * 1024) {
389 buff +=
seprintf(buff, last,
"%i", (
int)number);
390 }
else if (number < 1024 * 10) {
391 buff +=
seprintf(buff, last,
"%i%s%02i", (
int)number / 1024, decimal_separator, (
int)(number % 1024) * 100 / 1024);
392 }
else if (number < 1024 * 100) {
393 buff +=
seprintf(buff, last,
"%i%s%01i", (
int)number / 1024, decimal_separator, (
int)(number % 1024) * 10 / 1024);
395 assert(number < 1024 * 1024);
396 buff +=
seprintf(buff, last,
"%i", (
int)number / 1024);
399 assert(
id <
lengthof(iec_prefixes));
400 buff +=
seprintf(buff, last,
NBSP "%sB", iec_prefixes[
id]);
405 static char *FormatYmdString(
char *buff,
Date date,
const char *last, uint case_index)
410 int64 args[] = {ymd.
day + STR_DAY_NUMBER_1ST - 1, STR_MONTH_ABBREV_JAN + ymd.
month, ymd.
year};
412 return FormatString(buff, GetStringPtr(STR_FORMAT_DATE_LONG), &tmp_params, last, case_index);
415 static char *FormatMonthAndYear(
char *buff,
Date date,
const char *last, uint case_index)
420 int64 args[] = {STR_MONTH_JAN + ymd.
month, ymd.
year};
422 return FormatString(buff, GetStringPtr(STR_FORMAT_DATE_SHORT), &tmp_params, last, case_index);
425 static char *FormatTinyOrISODate(
char *buff,
Date date,
StringID str,
const char *last)
436 int64 args[] = {(int64)(
size_t)day, (int64)(
size_t)month, ymd.
year};
438 return FormatString(buff, GetStringPtr(str), &tmp_params, last);
441 static char *FormatGenericCurrency(
char *buff,
const CurrencySpec *spec,
Money number,
bool compact,
const char *last)
445 bool negative = number < 0;
446 const char *multiplier =
"";
448 number *= spec->rate;
452 if (buff +
Utf8CharLen(SCC_RED) > last)
return buff;
454 buff =
strecpy(buff,
"-", last);
467 if (number >= 1000000000 - 500) {
468 number = (number + 500000) / 1000000;
469 multiplier =
NBSP "M";
470 }
else if (number >= 1000000) {
471 number = (number + 500) / 1000;
472 multiplier =
NBSP "k";
477 if (separator == NULL && !
StrEmpty(_currency->separator)) separator = _currency->separator;
480 buff =
strecpy(buff, multiplier, last);
488 if (buff +
Utf8CharLen(SCC_PREVIOUS_COLOUR) > last)
return buff;
489 buff +=
Utf8Encode(buff, SCC_PREVIOUS_COLOUR);
505 uint64 n =
abs(count);
507 switch (plural_form) {
516 return n != 1 ? 1 : 0;
528 return n > 1 ? 1 : 0;
535 return n % 10 == 1 && n % 100 != 11 ? 0 : n != 0 ? 1 : 2;
541 return n == 1 ? 0 : n == 2 ? 1 : n < 7 ? 2 : n < 11 ? 3 : 4;
547 return n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
553 return n % 10 == 1 && n % 100 != 11 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
559 return n == 1 ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2;
565 return n % 100 == 1 ? 0 : n % 100 == 2 ? 1 : n % 100 == 3 || n % 100 == 4 ? 2 : 3;
571 return n % 10 == 1 && n % 100 != 11 ? 0 : 1;
577 return n == 1 ? 0 : n >= 2 && n <= 4 ? 1 : 2;
608 return (n == 1 ? 0 : n == 0 || (n % 100 > 1 && n % 100 < 11) ? 1 : (n % 100 > 10 && n % 100 < 20) ? 2 : 3);
613 return ((n == 1 || n == 11) ? 0 : (n == 2 || n == 12) ? 1 : ((n > 2 && n < 11) || (n > 12 && n < 20)) ? 2 : 3);
617 static const char *ParseStringChoice(
const char *b, uint form,
char **dst,
const char *last)
621 uint pos, i, mypos = 0;
623 for (i = pos = 0; i != n; i++) {
624 uint len = (byte)*b++;
625 if (i == form) mypos = pos;
629 *dst +=
seprintf(*dst, last,
"%s", b + mypos);
646 return ((input * this->multiplier) + (round && this->shift != 0 ? 1 << (this->shift - 1) : 0)) >> this->shift;
656 int64
FromDisplay(int64 input,
bool round =
true, int64 divider = 1)
const 658 return ((input << this->shift) + (round ? (this->multiplier * divider) - 1 : 0)) / (this->multiplier * divider);
677 { { 1, 0}, STR_UNITS_VELOCITY_IMPERIAL },
678 { { 103, 6}, STR_UNITS_VELOCITY_METRIC },
679 { {1831, 12}, STR_UNITS_VELOCITY_SI },
684 { { 1, 0}, STR_UNITS_POWER_IMPERIAL },
685 { {4153, 12}, STR_UNITS_POWER_METRIC },
686 { {6109, 13}, STR_UNITS_POWER_SI },
691 { {4515, 12}, STR_UNITS_WEIGHT_SHORT_IMPERIAL, STR_UNITS_WEIGHT_LONG_IMPERIAL },
692 { { 1, 0}, STR_UNITS_WEIGHT_SHORT_METRIC, STR_UNITS_WEIGHT_LONG_METRIC },
693 { {1000, 0}, STR_UNITS_WEIGHT_SHORT_SI, STR_UNITS_WEIGHT_LONG_SI },
698 { {4227, 4}, STR_UNITS_VOLUME_SHORT_IMPERIAL, STR_UNITS_VOLUME_LONG_IMPERIAL },
699 { {1000, 0}, STR_UNITS_VOLUME_SHORT_METRIC, STR_UNITS_VOLUME_LONG_METRIC },
700 { { 1, 0}, STR_UNITS_VOLUME_SHORT_SI, STR_UNITS_VOLUME_LONG_SI },
705 { {3597, 4}, STR_UNITS_FORCE_IMPERIAL },
706 { {3263, 5}, STR_UNITS_FORCE_METRIC },
707 { { 1, 0}, STR_UNITS_FORCE_SI },
712 { { 3, 0}, STR_UNITS_HEIGHT_IMPERIAL },
713 { { 1, 0}, STR_UNITS_HEIGHT_METRIC },
714 { { 1, 0}, STR_UNITS_HEIGHT_SI },
770 uint orig_offset = args->
offset;
782 FormatString(buff, str_arg, args, last, case_index, game_script,
true);
785 FormatString(buff, str_arg, args, last, case_index, game_script,
true);
788 args->
offset = orig_offset;
791 uint next_substr_case_index = 0;
792 char *buf_start = buff;
793 std::stack<const char *> str_stack;
794 str_stack.push(str_arg);
797 while (!str_stack.empty() && (b = Utf8Consume(&str_stack.top())) ==
'\0') {
800 if (str_stack.empty())
break;
801 const char *&str = str_stack.top();
807 if (b == 0)
continue;
812 uint64 sub_args_data[20];
813 WChar sub_args_type[20];
814 bool sub_args_need_free[20];
818 memset(sub_args_need_free, 0,
sizeof(sub_args_need_free));
822 uint32 stringid = strtoul(str, &p, 16);
823 if (*p !=
':' && *p !=
'\0') {
824 while (*p !=
'\0') p++;
826 buff =
strecat(buff,
"(invalid SCC_ENCODED)", last);
830 while (*p !=
'\0') p++;
832 buff =
strecat(buff,
"(invalid StringID)", last);
837 while (*p !=
'\0' && i < 20) {
842 bool instring =
false;
849 if (*p ==
'"' && escape) {
856 instring = !instring;
863 if (*p ==
':')
break;
864 if (*p ==
'\0')
break;
871 bool lookup = (l == SCC_ENCODED);
872 if (lookup) s += len;
874 param = strtoull(s, &p, 16);
878 while (*p !=
'\0') p++;
880 buff =
strecat(buff,
"(invalid sub-StringID)", last);
886 sub_args.SetParam(i++, param);
891 sub_args_need_free[i] =
true;
892 sub_args.SetParam(i++, (uint64)(
size_t)g);
901 for (
int i = 0; i < 20; i++) {
902 if (sub_args_need_free[i])
free((
void *)sub_args.GetParam(i));
908 StringID substr = Utf8Consume(&str);
909 str_stack.push(GetStringPtr(substr));
915 str_stack.push(GetStringPtr(substr));
916 case_index = next_substr_case_index;
917 next_substr_case_index = 0;
922 case SCC_GENDER_LIST: {
924 uint
offset = orig_offset + (byte)*str++;
945 WChar c = Utf8Consume(&s);
947 if (c == SCC_GENDER_INDEX) gender = (byte)s[0];
949 str = ParseStringChoice(str, gender, &buff, last);
955 case SCC_GENDER_INDEX:
964 case SCC_PLURAL_LIST: {
965 int plural_form = *str++;
966 uint
offset = orig_offset + (byte)*str++;
972 case SCC_ARG_INDEX: {
973 args->
offset = orig_offset + (byte)*str++;
980 next_substr_case_index = (byte)*str++;
984 case SCC_SWITCH_CASE: {
987 uint num = (byte)*str++;
989 if ((byte)str[0] == case_index) {
995 str += 3 + (str[1] << 8) + str[2];
1002 buff =
strecpy(buff, _openttd_revision, last);
1005 case SCC_RAW_STRING_POINTER: {
1006 if (game_script)
break;
1007 const char *str = (
const char *)(
size_t)args->
GetInt64(SCC_RAW_STRING_POINTER);
1019 buff =
GetStringWithArgs(buff, str, &tmp_params, last, next_substr_case_index, game_script);
1020 next_substr_case_index = 0;
1034 uint size = b - SCC_STRING1 + 1;
1036 buff =
strecat(buff,
"(too many parameters)", last);
1039 buff =
GetStringWithArgs(buff, str, &sub_args, last, next_substr_case_index, game_script);
1041 next_substr_case_index = 0;
1046 buff = FormatCommaNumber(buff, args->
GetInt64(SCC_COMMA), last);
1050 int64 number = args->
GetInt64(SCC_DECIMAL);
1051 int digits = args->
GetInt32(SCC_DECIMAL);
1052 buff = FormatCommaNumber(buff, number, last, digits);
1057 buff = FormatNoCommaNumber(buff, args->
GetInt64(SCC_NUM), last);
1060 case SCC_ZEROFILL_NUM: {
1062 buff = FormatZerofillNumber(buff, num, args->
GetInt64(), last);
1067 buff = FormatHexNumber(buff, (uint64)args->
GetInt64(SCC_HEX), last);
1074 case SCC_CARGO_TINY: {
1083 switch (cargo_str) {
1098 buff = FormatCommaNumber(buff, amount, last);
1102 case SCC_CARGO_SHORT: {
1110 switch (cargo_str) {
1136 case SCC_CARGO_LONG: {
1147 case SCC_CARGO_LIST: {
1148 uint32 cmask = args->
GetInt32(SCC_CARGO_LIST);
1155 if (buff >= last - 2)
break;
1169 if (first) buff =
GetStringWithArgs(buff, STR_JUST_NOTHING, args, last, next_substr_case_index, game_script);
1172 next_substr_case_index = 0;
1175 assert(buff < last);
1179 case SCC_CURRENCY_SHORT:
1180 buff = FormatGenericCurrency(buff, _currency, args->
GetInt64(),
true, last);
1183 case SCC_CURRENCY_LONG:
1184 buff = FormatGenericCurrency(buff, _currency, args->
GetInt64(SCC_CURRENCY_LONG),
false, last);
1188 buff = FormatTinyOrISODate(buff, args->
GetInt32(SCC_DATE_TINY), STR_FORMAT_DATE_TINY, last);
1191 case SCC_DATE_SHORT:
1192 buff = FormatMonthAndYear(buff, args->
GetInt32(SCC_DATE_SHORT), last, next_substr_case_index);
1193 next_substr_case_index = 0;
1197 buff = FormatYmdString(buff, args->
GetInt32(SCC_DATE_LONG), last, next_substr_case_index);
1198 next_substr_case_index = 0;
1202 buff = FormatTinyOrISODate(buff, args->
GetInt32(), STR_FORMAT_DATE_ISO, last);
1229 case SCC_VELOCITY: {
1237 case SCC_VOLUME_SHORT: {
1245 case SCC_VOLUME_LONG: {
1253 case SCC_WEIGHT_SHORT: {
1261 case SCC_WEIGHT_LONG: {
1269 case SCC_COMPANY_NAME: {
1271 if (c == NULL)
break;
1273 if (c->
name != NULL) {
1274 int64 args_array[] = {(int64)(
size_t)c->
name};
1278 int64 args_array[] = {c->
name_2};
1285 case SCC_COMPANY_NUM: {
1290 int64 args_array[] = {company + 1};
1297 case SCC_DEPOT_NAME: {
1300 uint64 args_array[] = {(uint64)args->
GetInt32()};
1301 WChar types_array[] = {SCC_STATION_NAME};
1303 buff =
GetStringWithArgs(buff, STR_FORMAT_DEPOT_NAME_AIRCRAFT, &tmp_params, last);
1308 if (d->name != NULL) {
1309 int64 args_array[] = {(int64)(
size_t)d->name};
1315 buff =
GetStringWithArgs(buff, STR_FORMAT_DEPOT_NAME_TRAIN + 2 * vt + (d->
town_cn == 0 ? 0 : 1), &tmp_params, last);
1320 case SCC_ENGINE_NAME: {
1322 if (e == NULL)
break;
1325 int64 args_array[] = {(int64)(
size_t)e->
name};
1335 case SCC_GROUP_NAME: {
1337 if (g == NULL)
break;
1339 if (g->
name != NULL) {
1340 int64 args_array[] = {(int64)(
size_t)g->
name};
1344 int64 args_array[] = {g->
index};
1352 case SCC_INDUSTRY_NAME: {
1354 if (i == NULL)
break;
1366 buff =
FormatString(buff, GetStringPtr(STR_FORMAT_INDUSTRY_NAME), &tmp_params, last, next_substr_case_index);
1368 next_substr_case_index = 0;
1372 case SCC_PRESIDENT_NAME: {
1374 if (c == NULL)
break;
1388 case SCC_STATION_NAME: {
1389 StationID sid = args->
GetInt32(SCC_STATION_NAME);
1401 if (st->
name != NULL) {
1402 int64 args_array[] = {(int64)(
size_t)st->
name};
1407 if (st->
indtype != IT_INVALID) {
1419 int64 args_array[] = {STR_TOWN_NAME, st->
town->
index, st->
index};
1426 case SCC_TOWN_NAME: {
1428 if (t == NULL)
break;
1430 if (t->
name != NULL) {
1431 int64 args_array[] = {(int64)(
size_t)t->
name};
1440 case SCC_WAYPOINT_NAME: {
1442 if (wp == NULL)
break;
1444 if (wp->
name != NULL) {
1445 int64 args_array[] = {(int64)(
size_t)wp->
name};
1451 StringID str = ((wp->
string_id == STR_SV_STNAME_BUOY) ? STR_FORMAT_BUOY_NAME : STR_FORMAT_WAYPOINT_NAME);
1458 case SCC_VEHICLE_NAME: {
1460 if (v == NULL)
break;
1462 if (v->
name != NULL) {
1463 int64 args_array[] = {(int64)(
size_t)v->
name};
1472 default: str = STR_INVALID_VEHICLE;
break;
1473 case VEH_TRAIN: str = STR_SV_TRAIN_NAME;
break;
1474 case VEH_ROAD: str = STR_SV_ROAD_VEHICLE_NAME;
break;
1475 case VEH_SHIP: str = STR_SV_SHIP_NAME;
break;
1484 case SCC_SIGN_NAME: {
1486 if (si == NULL)
break;
1488 if (si->name != NULL) {
1489 int64 args_array[] = {(int64)(
size_t)si->name};
1499 case SCC_STATION_FEATURES: {
1500 buff = StationGetSpecialString(buff, args->
GetInt32(SCC_STATION_FEATURES), last);
1514 static char *StationGetSpecialString(
char *buff,
int x,
const char *last)
1525 static char *GetSpecialTownNameString(
char *buff,
int ind, uint32 seed,
const char *last)
1530 static const char *
const _silly_company_names[] = {
1532 "Tiny Transport Ltd.",
1534 "Comfy-Coach & Co.",
1535 "Crush & Bump Ltd.",
1536 "Broken & Late Ltd.",
1538 "Supersonic Travel",
1540 "Lightning International",
1541 "Pannik & Loozit Ltd.",
1542 "Inter-City Transport",
1543 "Getout & Pushit Ltd." 1546 static const char *
const _surname_list[] = {
1578 static const char *
const _silly_surname_list[] = {
1593 static const char _initial_name_letters[] = {
1594 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
1595 'K',
'L',
'M',
'N',
'P',
'R',
'S',
'T',
'W',
1598 static char *GenAndCoName(
char *buff, uint32 arg,
const char *last)
1600 const char *
const *base;
1604 base = _silly_surname_list;
1605 num =
lengthof(_silly_surname_list);
1607 base = _surname_list;
1611 buff =
strecpy(buff, base[num *
GB(arg, 16, 8) >> 8], last);
1612 buff =
strecpy(buff,
" & Co.", last);
1617 static char *GenPresidentName(
char *buff, uint32 x,
const char *last)
1619 char initial[] =
"?. ";
1620 const char *
const *base;
1624 initial[0] = _initial_name_letters[
sizeof(_initial_name_letters) *
GB(x, 0, 8) >> 8];
1625 buff =
strecpy(buff, initial, last);
1627 i = (
sizeof(_initial_name_letters) + 35) *
GB(x, 8, 8) >> 8;
1628 if (i <
sizeof(_initial_name_letters)) {
1629 initial[0] = _initial_name_letters[i];
1630 buff =
strecpy(buff, initial, last);
1634 base = _silly_surname_list;
1635 num =
lengthof(_silly_surname_list);
1637 base = _surname_list;
1641 buff =
strecpy(buff, base[num *
GB(x, 16, 8) >> 8], last);
1646 static char *GetSpecialNameString(
char *buff,
int ind,
StringParameters *args,
const char *last)
1653 return GenAndCoName(buff, args->
GetInt32(), last);
1656 return GenPresidentName(buff, args->
GetInt32(), last);
1660 if (
IsInsideMM(ind - 6, 0, SPECSTR_TOWNNAME_LAST - SPECSTR_TOWNNAME_START + 1)) {
1661 buff = GetSpecialTownNameString(buff, ind - 6, args->
GetInt32(), last);
1662 return strecpy(buff,
" Transport", last);
1666 if (
IsInsideMM(ind, (SPECSTR_LANGUAGE_START - 0x70E4), (SPECSTR_LANGUAGE_END - 0x70E4) + 1)) {
1667 int i = ind - (SPECSTR_LANGUAGE_START - 0x70E4);
1669 &_languages[i] == _current_language ? _current_language->
own_name : _languages[i].name, last);
1673 if (
IsInsideMM(ind, (SPECSTR_RESOLUTION_START - 0x70E4), (SPECSTR_RESOLUTION_END - 0x70E4) + 1)) {
1674 int i = ind - (SPECSTR_RESOLUTION_START - 0x70E4);
1684 #ifdef ENABLE_NETWORK 1685 extern void SortNetworkLanguages();
1687 static inline void SortNetworkLanguages() {}
1697 this->version == TO_LE32(LANGUAGE_PACK_VERSION) &&
1698 this->plural_form < LANGUAGE_MAX_PLURAL &&
1699 this->text_dir <= 1 &&
1706 StrValid(this->digit_group_separator,
lastof(this->digit_group_separator)) &&
1707 StrValid(this->digit_group_separator_currency,
lastof(this->digit_group_separator_currency)) &&
1708 StrValid(this->digit_decimal_separator,
lastof(this->digit_decimal_separator));
1721 if (lang_pack == NULL)
return false;
1724 const char *end = (
char *)lang_pack + len + 1;
1727 if (end <= lang_pack->
data || !lang_pack->
IsValid()) {
1732 #if TTD_ENDIAN == TTD_BIG_ENDIAN 1740 uint16 num = lang_pack->
offsets[i];
1752 char **langpack_offs = MallocT<char *>(count);
1755 char *s = lang_pack->data;
1757 for (uint i = 0; i < count; i++) {
1758 if (s + len >= end) {
1760 free(langpack_offs);
1764 len = ((len & 0x3F) << 8) + (byte)*s++;
1765 if (s + len >= end) {
1767 free(langpack_offs);
1771 langpack_offs[i] = s;
1778 _langpack = lang_pack;
1780 free(_langpack_offs);
1781 _langpack_offs = langpack_offs;
1783 _current_language = lang;
1785 const char *c_file = strrchr(_current_language->
file, PATHSEPCHAR) + 1;
1789 #ifdef WITH_ICU_SORT 1797 UErrorCode status = U_ZERO_ERROR;
1802 if (U_FAILURE(status)) {
1813 SortNetworkLanguages();
1814 #ifdef ENABLE_NETWORK 1830 #if !(defined(WIN32) || defined(__APPLE__)) 1843 env = getenv(
"LANGUAGE");
1844 if (env != NULL)
return env;
1846 env = getenv(
"LC_ALL");
1847 if (env != NULL)
return env;
1849 if (param != NULL) {
1850 env = getenv(param);
1851 if (env != NULL)
return env;
1854 return getenv(
"LANG");
1864 GetString(stra, *a,
lastof(stra));
1865 GetString(strb, *b,
lastof(strb));
1878 if (newgrflangid == lang->newgrflangid)
return lang;
1892 FILE *f = fopen(file,
"rb");
1893 if (f == NULL)
return false;
1895 size_t read = fread(hdr,
sizeof(*hdr), 1, f);
1898 bool ret = read == 1 && hdr->
IsValid();
1916 struct dirent *dirent;
1917 while ((dirent = readdir(dir)) != NULL) {
1918 const char *d_name =
FS2OTTD(dirent->d_name);
1919 const char *extension = strrchr(d_name,
'.');
1922 if (extension == NULL || strcmp(extension,
".lng") != 0)
continue;
1929 DEBUG(misc, 3,
"%s is not a valid language file", lmd.
file);
1931 DEBUG(misc, 3,
"%s's language ID is already known", lmd.
file);
1933 *_languages.
Append() = lmd;
1949 char path[MAX_PATH];
1953 if (_languages.
Length() == 0)
usererror(
"No available language packs (invalid versions?)");
1957 if (lang == NULL) lang =
"en_GB";
1968 const char *lang_file = strrchr(lng->file, PATHSEPCHAR) + 1;
1970 chosen_language = lng;
1974 if (strcmp (lng->isocode,
"en_GB") == 0) en_GB_fallback = lng;
1975 if (strncmp(lng->isocode, lang, 5) == 0) chosen_language = lng;
1976 if (strncmp(lng->isocode, lang, 2) == 0) language_fallback = lng;
1981 if (chosen_language == NULL) {
1982 chosen_language = (language_fallback != NULL) ? language_fallback : en_GB_fallback;
2006 const Sprite *question_mark[FS_END];
2009 question_mark[size] =
GetGlyph(size,
'?');
2013 for (
const char *text = this->NextString(); text != NULL; text = this->NextString()) {
2014 FontSize size = this->DefaultSize();
2015 if (str != NULL) *str = text;
2016 for (
WChar c = Utf8Consume(&text); c !=
'\0'; c = Utf8Consume(&text)) {
2050 const char *ret = _langpack_offs[
_langtab_start[this->i] + this->j];
2053 while (this->i < TEXT_TAB_END && this->j >=
_langtab_num[this->i]) {
2068 #ifdef WITH_FREETYPE 2092 if (searcher == NULL) searcher = &pack_searcher;
2094 #ifdef WITH_FREETYPE 2099 memcpy(&backup, &_freetype,
sizeof(backup));
2103 memcpy(&_freetype, &backup,
sizeof(backup));
2105 if (bad_font && base_font) {
2120 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.");
2133 #if !defined(WITH_ICU_LAYOUT) 2148 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.
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.
#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 #_decode_parameters.
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.
Collator * _current_collator
Collator for the language currently in use.
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.
Index of the small font in the font tables.
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.
Index of the large font in the font tables.
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.
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.