Merge branch 'master' into jgrpp
# Conflicts: # cmake/CompileFlags.cmake # src/crashlog.cpp # src/fileio.cpp # src/fileio_func.h # src/fios_gui.cpp # src/ini_load.cpp # src/ini_type.h # src/lang/english.txt # src/lang/german.txt # src/lang/korean.txt # src/network/network_client.cpp # src/order_base.h # src/order_cmd.cpp # src/os/windows/win32.cpp # src/road_cmd.cpp # src/saveload/saveload.cpp # src/saveload/saveload.h # src/settings.cpp # src/station_cmd.cpp # src/stdafx.h # src/table/settings.ini # src/tree_cmd.cpp # src/tree_gui.cpp # src/vehicle_base.h # src/video/cocoa/cocoa_v.mm # src/video/cocoa/event.mm # src/video/cocoa/wnd_quartz.mm # src/viewport.cpp # src/widgets/tree_widget.h
This commit is contained in:
109
src/strings.cpp
109
src/strings.cpp
@@ -43,14 +43,14 @@
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
char _config_language_file[MAX_PATH]; ///< The file (name) stored in the configuration.
|
||||
std::string _config_language_file; ///< The file (name) stored in the configuration.
|
||||
LanguageList _languages; ///< The actual list of language meta data.
|
||||
const LanguageMetadata *_current_language = nullptr; ///< The currently loaded language.
|
||||
|
||||
TextDirection _current_text_dir; ///< Text direction of the currently selected language.
|
||||
|
||||
#ifdef WITH_ICU_I18N
|
||||
icu::Collator *_current_collator = nullptr; ///< Collator for the language currently in use.
|
||||
std::unique_ptr<icu::Collator> _current_collator; ///< Collator for the language currently in use.
|
||||
#endif /* WITH_ICU_I18N */
|
||||
|
||||
static uint64 _global_string_params_data[20]; ///< Global array of string parameters. To access, use #SetDParam.
|
||||
@@ -187,10 +187,17 @@ struct LanguagePack : public LanguagePackHeader {
|
||||
char data[]; // list of strings
|
||||
};
|
||||
|
||||
static char **_langpack_offs;
|
||||
static LanguagePack *_langpack;
|
||||
static uint _langtab_num[TEXT_TAB_END]; ///< Offset into langpack offs
|
||||
static uint _langtab_start[TEXT_TAB_END]; ///< Offset into langpack offs
|
||||
struct LoadedLanguagePack {
|
||||
std::unique_ptr<LanguagePack> langpack;
|
||||
|
||||
std::vector<char *> offsets;
|
||||
|
||||
std::array<uint, TEXT_TAB_END> langtab_num; ///< Offset into langpack offs
|
||||
std::array<uint, TEXT_TAB_END> langtab_start; ///< Offset into langpack offs
|
||||
};
|
||||
|
||||
static LoadedLanguagePack _langpack;
|
||||
|
||||
static bool _scan_for_gender_data = false; ///< Are we scanning for the gender of the current string? (instead of formatting it)
|
||||
|
||||
|
||||
@@ -201,7 +208,7 @@ const char *GetStringPtr(StringID string)
|
||||
/* 0xD0xx and 0xD4xx IDs have been converted earlier. */
|
||||
case TEXT_TAB_OLD_NEWGRF: NOT_REACHED();
|
||||
case TEXT_TAB_NEWGRF_START: return GetGRFStringPtr(GetStringIndex(string));
|
||||
default: return _langpack_offs[_langtab_start[GetStringTab(string)] + GetStringIndex(string)];
|
||||
default: return _langpack.offsets[_langpack.langtab_start[GetStringTab(string)] + GetStringIndex(string)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,7 +262,7 @@ char *GetStringWithArgs(char *buffr, StringID string, StringParameters *args, co
|
||||
break;
|
||||
}
|
||||
|
||||
if (index >= _langtab_num[tab]) {
|
||||
if (index >= _langpack.langtab_num[tab]) {
|
||||
if (game_script) {
|
||||
return GetStringWithArgs(buffr, STR_UNDEFINED, args, last);
|
||||
}
|
||||
@@ -320,7 +327,7 @@ static char *FormatNumber(char *buff, int64 number, const char *last, const char
|
||||
for (int i = 0; i < max_digits; i++) {
|
||||
if (i == max_digits - fractional_digits) {
|
||||
const char *decimal_separator = _settings_game.locale.digit_decimal_separator;
|
||||
if (decimal_separator == nullptr) decimal_separator = _langpack->digit_decimal_separator;
|
||||
if (decimal_separator == nullptr) decimal_separator = _langpack.langpack->digit_decimal_separator;
|
||||
buff += seprintf(buff, last, "%s", decimal_separator);
|
||||
}
|
||||
|
||||
@@ -345,7 +352,7 @@ static char *FormatNumber(char *buff, int64 number, const char *last, const char
|
||||
static char *FormatCommaNumber(char *buff, int64 number, const char *last, int fractional_digits = 0)
|
||||
{
|
||||
const char *separator = _settings_game.locale.digit_group_separator;
|
||||
if (separator == nullptr) separator = _langpack->digit_group_separator;
|
||||
if (separator == nullptr) separator = _langpack.langpack->digit_group_separator;
|
||||
return FormatNumber(buff, number, last, separator, 1, fractional_digits);
|
||||
}
|
||||
|
||||
@@ -368,7 +375,7 @@ WChar GetDecimalSeparatorChar()
|
||||
{
|
||||
WChar decimal_char = '.';
|
||||
const char *decimal_separator = _settings_game.locale.digit_decimal_separator;
|
||||
if (decimal_separator == nullptr) decimal_separator = _langpack->digit_decimal_separator;
|
||||
if (decimal_separator == nullptr) decimal_separator = _langpack.langpack->digit_decimal_separator;
|
||||
if (decimal_separator != nullptr) Utf8Decode(&decimal_char, decimal_separator);
|
||||
return decimal_char;
|
||||
}
|
||||
@@ -393,7 +400,7 @@ static char *FormatBytes(char *buff, int64 number, const char *last)
|
||||
}
|
||||
|
||||
const char *decimal_separator = _settings_game.locale.digit_decimal_separator;
|
||||
if (decimal_separator == nullptr) decimal_separator = _langpack->digit_decimal_separator;
|
||||
if (decimal_separator == nullptr) decimal_separator = _langpack.langpack->digit_decimal_separator;
|
||||
|
||||
if (number < 1024) {
|
||||
id = 0;
|
||||
@@ -521,7 +528,7 @@ static char *FormatGenericCurrency(char *buff, const CurrencySpec *spec, Money n
|
||||
|
||||
const char *separator = _settings_game.locale.digit_group_separator_currency;
|
||||
if (separator == nullptr && !StrEmpty(_currency->separator)) separator = _currency->separator;
|
||||
if (separator == nullptr) separator = _langpack->digit_group_separator_currency;
|
||||
if (separator == nullptr) separator = _langpack.langpack->digit_group_separator_currency;
|
||||
buff = FormatNumber(buff, number, last, separator);
|
||||
buff = strecpy(buff, multiplier, last);
|
||||
|
||||
@@ -2038,16 +2045,15 @@ bool LanguagePackHeader::IsValid() const
|
||||
bool ReadLanguagePack(const LanguageMetadata *lang)
|
||||
{
|
||||
/* Current language pack */
|
||||
size_t len;
|
||||
LanguagePack *lang_pack = (LanguagePack *)ReadFileToMem(lang->file, &len, 1U << 20);
|
||||
if (lang_pack == nullptr) return false;
|
||||
size_t len = 0;
|
||||
std::unique_ptr<LanguagePack> lang_pack(reinterpret_cast<LanguagePack *>(ReadFileToMem(lang->file, len, 1U << 20).release()));
|
||||
if (!lang_pack) return false;
|
||||
|
||||
/* End of read data (+ terminating zero added in ReadFileToMem()) */
|
||||
const char *end = (char *)lang_pack + len + 1;
|
||||
const char *end = (char *)lang_pack.get() + len + 1;
|
||||
|
||||
/* We need at least one byte of lang_pack->data */
|
||||
if (end <= lang_pack->data || !lang_pack->IsValid()) {
|
||||
free(lang_pack);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2057,55 +2063,46 @@ bool ReadLanguagePack(const LanguageMetadata *lang)
|
||||
}
|
||||
#endif /* TTD_ENDIAN == TTD_BIG_ENDIAN */
|
||||
|
||||
std::array<uint, TEXT_TAB_END> tab_start, tab_num;
|
||||
|
||||
uint count = 0;
|
||||
for (uint i = 0; i < TEXT_TAB_END; i++) {
|
||||
uint16 num = lang_pack->offsets[i];
|
||||
if (num > TAB_SIZE) {
|
||||
free(lang_pack);
|
||||
return false;
|
||||
}
|
||||
if (num > TAB_SIZE) return false;
|
||||
|
||||
_langtab_start[i] = count;
|
||||
_langtab_num[i] = num;
|
||||
tab_start[i] = count;
|
||||
tab_num[i] = num;
|
||||
count += num;
|
||||
}
|
||||
|
||||
/* Allocate offsets */
|
||||
char **langpack_offs = MallocT<char *>(count);
|
||||
std::vector<char *> offs(count);
|
||||
|
||||
/* Fill offsets */
|
||||
char *s = lang_pack->data;
|
||||
len = (byte)*s++;
|
||||
for (uint i = 0; i < count; i++) {
|
||||
if (s + len >= end) {
|
||||
free(lang_pack);
|
||||
free(langpack_offs);
|
||||
return false;
|
||||
}
|
||||
if (s + len >= end) return false;
|
||||
|
||||
if (len >= 0xC0) {
|
||||
len = ((len & 0x3F) << 8) + (byte)*s++;
|
||||
if (s + len >= end) {
|
||||
free(lang_pack);
|
||||
free(langpack_offs);
|
||||
return false;
|
||||
}
|
||||
if (s + len >= end) return false;
|
||||
}
|
||||
langpack_offs[i] = s;
|
||||
offs[i] = s;
|
||||
s += len;
|
||||
len = (byte)*s;
|
||||
*s++ = '\0'; // zero terminate the string
|
||||
}
|
||||
|
||||
free(_langpack);
|
||||
_langpack = lang_pack;
|
||||
|
||||
free(_langpack_offs);
|
||||
_langpack_offs = langpack_offs;
|
||||
_langpack.langpack = std::move(lang_pack);
|
||||
_langpack.offsets = std::move(offs);
|
||||
_langpack.langtab_num = tab_num;
|
||||
_langpack.langtab_start = tab_start;
|
||||
|
||||
_current_language = lang;
|
||||
_current_text_dir = (TextDirection)_current_language->text_dir;
|
||||
const char *c_file = strrchr(_current_language->file, PATHSEPCHAR) + 1;
|
||||
strecpy(_config_language_file, c_file, lastof(_config_language_file));
|
||||
_config_language_file = c_file;
|
||||
SetCurrentGrfLangID(_current_language->newgrflangid);
|
||||
|
||||
#ifdef _WIN32
|
||||
@@ -2119,21 +2116,14 @@ bool ReadLanguagePack(const LanguageMetadata *lang)
|
||||
#endif
|
||||
|
||||
#ifdef WITH_ICU_I18N
|
||||
/* Delete previous collator. */
|
||||
if (_current_collator != nullptr) {
|
||||
delete _current_collator;
|
||||
_current_collator = nullptr;
|
||||
}
|
||||
|
||||
/* Create a collator instance for our current locale. */
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
_current_collator = icu::Collator::createInstance(icu::Locale(_current_language->isocode), status);
|
||||
_current_collator.reset(icu::Collator::createInstance(icu::Locale(_current_language->isocode), status));
|
||||
/* Sort number substrings by their numerical value. */
|
||||
if (_current_collator != nullptr) _current_collator->setAttribute(UCOL_NUMERIC_COLLATION, UCOL_ON, status);
|
||||
if (_current_collator) _current_collator->setAttribute(UCOL_NUMERIC_COLLATION, UCOL_ON, status);
|
||||
/* Avoid using the collator if it is not correctly set. */
|
||||
if (U_FAILURE(status)) {
|
||||
delete _current_collator;
|
||||
_current_collator = nullptr;
|
||||
_current_collator.reset();
|
||||
}
|
||||
#endif /* WITH_ICU_I18N */
|
||||
|
||||
@@ -2277,9 +2267,8 @@ void InitializeLanguagePacks()
|
||||
Searchpath sp;
|
||||
|
||||
FOR_ALL_SEARCHPATHS(sp) {
|
||||
char path[MAX_PATH];
|
||||
FioAppendDirectory(path, lastof(path), sp, LANG_DIR);
|
||||
GetLanguageList(path);
|
||||
std::string path = FioGetDirectory(sp, LANG_DIR);
|
||||
GetLanguageList(path.c_str());
|
||||
}
|
||||
if (_languages.size() == 0) usererror("No available language packs (invalid versions?)");
|
||||
|
||||
@@ -2297,7 +2286,7 @@ void InitializeLanguagePacks()
|
||||
* configuration file, local environment and last, if nothing found,
|
||||
* English. */
|
||||
const char *lang_file = strrchr(lng.file, PATHSEPCHAR) + 1;
|
||||
if (strcmp(lang_file, _config_language_file) == 0) {
|
||||
if (_config_language_file == lang_file) {
|
||||
chosen_language = &lng;
|
||||
break;
|
||||
}
|
||||
@@ -2322,7 +2311,7 @@ void InitializeLanguagePacks()
|
||||
*/
|
||||
const char *GetCurrentLanguageIsoCode()
|
||||
{
|
||||
return _langpack->isocode;
|
||||
return _langpack.langpack->isocode;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2376,10 +2365,10 @@ class LanguagePackGlyphSearcher : public MissingGlyphSearcher {
|
||||
{
|
||||
if (this->i >= TEXT_TAB_END) return nullptr;
|
||||
|
||||
const char *ret = _langpack_offs[_langtab_start[this->i] + this->j];
|
||||
const char *ret = _langpack.offsets[_langpack.langtab_start[this->i] + this->j];
|
||||
|
||||
this->j++;
|
||||
while (this->i < TEXT_TAB_END && this->j >= _langtab_num[this->i]) {
|
||||
while (this->i < TEXT_TAB_END && this->j >= _langpack.langtab_num[this->i]) {
|
||||
this->i++;
|
||||
this->j = 0;
|
||||
}
|
||||
@@ -2435,7 +2424,7 @@ void CheckForMissingGlyphs(bool base_font, MissingGlyphSearcher *searcher)
|
||||
_freetype.mono.os_handle = nullptr;
|
||||
_freetype.medium.os_handle = nullptr;
|
||||
|
||||
bad_font = !SetFallbackFont(&_freetype, _langpack->isocode, _langpack->winlangid, searcher);
|
||||
bad_font = !SetFallbackFont(&_freetype, _langpack.langpack->isocode, _langpack.langpack->winlangid, searcher);
|
||||
|
||||
free(_freetype.mono.os_handle);
|
||||
free(_freetype.medium.os_handle);
|
||||
|
Reference in New Issue
Block a user