1
0
Fork 0

Compare commits

..

20 Commits

Author SHA1 Message Date
Peter Nelson f06b3e9846
Change: Use CARGO_LIST to show station cargo acceptance changes. (#11379)
This simplifies construction of the news message and allows for more than
two changes to be show in one line.
2023-10-20 20:14:46 +01:00
translators 4c24334fda Update: Translations from eints 2023-10-20 18:38:26 +00:00
Peter Nelson fd6f1e844a
Codechange: Avoid emplace_back(new()) into a unique_ptr. (#11384)
This could theoretically leave an unmanaged pointer in certain circumstances, and directly using
make_unique shows intent.
2023-10-20 18:40:48 +01:00
Peter Nelson 429a6f58e7
Codechange: Use max_element to find best cargo (sub-)type in NewGRF var 42. (#11370)
This replaces two manual loops to find the best cargo (sub-)type.
2023-10-20 18:40:26 +01:00
Peter Nelson 90351578a6 Codechange: Use std::map instead of fixed array to store refit options.
This simplifies handling of available refit options.
2023-10-20 18:39:32 +01:00
Peter Nelson e4f94747f3 Codechange: Use comparator struct to sort cargo ID by predefined sort order.
This allows reuse of the comparator where a typename is used instead.
2023-10-20 18:39:32 +01:00
Peter Nelson bc8e26f4e7
Codechange: Simplify usage of GRFFile cargo_map. (#11349) 2023-10-20 18:38:54 +01:00
Peter Nelson 69e20e79ab Codechange: Add const versions of GetItem/GetGroup, and sprinkle liberally.
Non-const version of GetItem is not needed.
2023-10-20 18:37:27 +01:00
Peter Nelson 17ba9d8c96 Codechange: Use range-for instead of nullptr-terminated list in settingsgen.
This simplifies iteration and avoids use of pointers.
2023-10-20 18:37:27 +01:00
Peter Nelson 233aac567b Codechange: Use std::list instead of C-linked list for ini files.
This removes self-management of memory with new/delete and allows simpler iteration.
2023-10-20 18:37:27 +01:00
Peter Nelson ec1cf96b62 Codechange: Move initialization of group-type to CreateGroup function. 2023-10-20 18:37:27 +01:00
Peter Nelson 8bd06807e4 Codechange: Pass initializer list instead of null-terminated list of group types. 2023-10-20 18:37:27 +01:00
Peter Nelson 1fecbeff76 Codechange: Remove create parameter from IniLoadFile::GetGroup.
GetGroup now only returns nullptr if the group does not exist.
Use GetOrCreateGroup to create a group.

This avoids creating groups while reading ini files.
2023-10-20 18:37:27 +01:00
Peter Nelson c47a0e1578 Codechange: Correct scope of IniItem for for-loop. 2023-10-20 18:37:27 +01:00
Peter Nelson 6ce7195ef1 Codechange: Split GetGroup into GetGroup/GetOrCreateGroup.
This follows the pattern used for GetItem/GetOrCreateItem, and allows use
of references where we know the group must exist.
2023-10-20 18:37:27 +01:00
Peter Nelson 54b1a067eb Codechange: Test for nullptr instead of treating pointer as boolean. 2023-10-20 18:37:27 +01:00
Peter Nelson d3c5ae2648 Codechange: Add CreateGroup/CreateItem methods for ini files.
This abstracts the internals a bit.
2023-10-20 18:37:27 +01:00
Peter Nelson 0c85ce29ea Codechange: Pass ini file by reference and prefer automatic storage.
This avoids new/delete operations, and (not) checking for nullptr.
2023-10-20 18:37:27 +01:00
Peter Nelson 3961318974 Codechange: Accept std::string in RemoveGroup(). 2023-10-20 18:37:27 +01:00
Peter Nelson bb6fa9bf3b
Change: Display cargo lists in sorted cargo order. (#11383) 2023-10-20 17:32:17 +01:00
98 changed files with 536 additions and 724 deletions

View File

@ -241,7 +241,7 @@ class BuildAirportWindow : public PickerWindowBase {
DropDownList list;
for (uint i = 0; i < AirportClass::GetClassCount(); i++) {
list.emplace_back(new DropDownListStringItem(AirportClass::Get((AirportClassID)i)->name, i, false));
list.push_back(std::make_unique<DropDownListStringItem>(AirportClass::Get((AirportClassID)i)->name, i, false));
}
return list;

View File

@ -568,8 +568,8 @@ public:
case WID_RV_TRAIN_ENGINEWAGON_DROPDOWN: {
DropDownList list;
list.emplace_back(new DropDownListStringItem(STR_REPLACE_ENGINES, 1, false));
list.emplace_back(new DropDownListStringItem(STR_REPLACE_WAGONS, 0, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_REPLACE_ENGINES, 1, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_REPLACE_WAGONS, 0, false));
ShowDropDownList(this, std::move(list), this->replace_engines ? 1 : 0, WID_RV_TRAIN_ENGINEWAGON_DROPDOWN);
break;
}

View File

@ -95,7 +95,7 @@ struct BaseSet {
return Tnum_files - this->valid_files;
}
bool FillSetDetails(IniFile *ini, const std::string &path, const std::string &full_filename, bool allow_empty_filename = true);
bool FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename, bool allow_empty_filename = true);
/**
* Get the description for the given ISO code.
@ -244,7 +244,7 @@ struct GraphicsSet : BaseSet<GraphicsSet, MAX_GFT, true> {
PaletteType palette; ///< Palette of this graphics set
BlitterType blitter; ///< Blitter of this graphics set
bool FillSetDetails(struct IniFile *ini, const std::string &path, const std::string &full_filename);
bool FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename);
static MD5File::ChecksumResult CheckMD5(const MD5File *file, Subdirectory subdir);
};
@ -301,7 +301,7 @@ struct MusicSet : BaseSet<MusicSet, NUM_SONGS_AVAILABLE, false> {
/** Number of valid songs in set. */
byte num_available;
bool FillSetDetails(struct IniFile *ini, const std::string &path, const std::string &full_filename);
bool FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename);
};
/** All data/functions related with replacing the base music */

View File

@ -39,10 +39,15 @@ extern void CheckExternalFiles();
* @return true if loading was successful.
*/
template <class T, size_t Tnum_files, bool Tsearch_in_tars>
bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(IniFile *ini, const std::string &path, const std::string &full_filename, bool allow_empty_filename)
bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename, bool allow_empty_filename)
{
IniGroup *metadata = ini->GetGroup("metadata");
IniItem *item;
const IniGroup *metadata = ini.GetGroup("metadata");
if (metadata == nullptr) {
Debug(grf, 0, "Base " SET_TYPE "set detail loading: metadata missing.");
Debug(grf, 0, " Is {} readable for the user running OpenTTD?", full_filename);
return false;
}
const IniItem *item;
fetch_metadata("name");
this->name = *item->value;
@ -51,10 +56,10 @@ bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(IniFile *ini, const
this->description[std::string{}] = *item->value;
/* Add the translations of the descriptions too. */
for (item = metadata->item; item != nullptr; item = item->next) {
if (item->name.compare(0, 12, "description.") != 0) continue;
for (const IniItem &titem : metadata->items) {
if (titem.name.compare(0, 12, "description.") != 0) continue;
this->description[item->name.substr(12)] = item->value.value_or("");
this->description[titem.name.substr(12)] = titem.value.value_or("");
}
fetch_metadata("shortname");
@ -69,13 +74,13 @@ bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(IniFile *ini, const
this->fallback = (item != nullptr && item->value && *item->value != "0" && *item->value != "false");
/* For each of the file types we want to find the file, MD5 checksums and warning messages. */
IniGroup *files = ini->GetGroup("files");
IniGroup *md5s = ini->GetGroup("md5s");
IniGroup *origin = ini->GetGroup("origin");
const IniGroup *files = ini.GetGroup("files");
const IniGroup *md5s = ini.GetGroup("md5s");
const IniGroup *origin = ini.GetGroup("origin");
for (uint i = 0; i < Tnum_files; i++) {
MD5File *file = &this->files[i];
/* Find the filename first. */
item = files->GetItem(BaseSet<T, Tnum_files, Tsearch_in_tars>::file_names[i]);
item = files != nullptr ? files->GetItem(BaseSet<T, Tnum_files, Tsearch_in_tars>::file_names[i]) : nullptr;
if (item == nullptr || (!item->value.has_value() && !allow_empty_filename)) {
Debug(grf, 0, "No " SET_TYPE " file for: {} (in {})", BaseSet<T, Tnum_files, Tsearch_in_tars>::file_names[i], full_filename);
return false;
@ -93,7 +98,7 @@ bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(IniFile *ini, const
file->filename = path + filename;
/* Then find the MD5 checksum */
item = md5s->GetItem(filename);
item = md5s != nullptr ? md5s->GetItem(filename) : nullptr;
if (item == nullptr || !item->value.has_value()) {
Debug(grf, 0, "No MD5 checksum specified for: {} (in {})", filename, full_filename);
return false;
@ -119,8 +124,8 @@ bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(IniFile *ini, const
}
/* Then find the warning message when the file's missing */
item = origin->GetItem(filename);
if (item == nullptr) item = origin->GetItem("default");
item = origin != nullptr ? origin->GetItem(filename) : nullptr;
if (item == nullptr) item = origin != nullptr ? origin->GetItem("default") : nullptr;
if (item == nullptr || !item->value.has_value()) {
Debug(grf, 1, "No origin warning message specified for: {}", filename);
file->missing_warning.clear();
@ -159,9 +164,9 @@ bool BaseMedia<Tbase_set>::AddFile(const std::string &filename, size_t basepath_
Debug(grf, 1, "Checking {} for base " SET_TYPE " set", filename);
Tbase_set *set = new Tbase_set();
IniFile *ini = new IniFile();
IniFile ini{};
std::string path{ filename, basepath_length };
ini->LoadFromDisk(path, BASESET_DIR);
ini.LoadFromDisk(path, BASESET_DIR);
auto psep = path.rfind(PATHSEPCHAR);
if (psep != std::string::npos) {
@ -218,7 +223,6 @@ bool BaseMedia<Tbase_set>::AddFile(const std::string &filename, size_t basepath_
delete set;
}
delete ini;
return ret;
}

View File

@ -574,11 +574,12 @@ static uint GetCargoWeight(const CargoArray &cap, VehicleType vtype)
static int DrawCargoCapacityInfo(int left, int right, int y, TestedEngineDetails &te, bool refittable)
{
for (CargoID c = 0; c < NUM_CARGO; c++) {
if (te.all_capacities[c] == 0) continue;
for (const CargoSpec *cs : _sorted_cargo_specs) {
CargoID cid = cs->Index();
if (te.all_capacities[cid] == 0) continue;
SetDParam(0, c);
SetDParam(1, te.all_capacities[c]);
SetDParam(0, cid);
SetDParam(1, te.all_capacities[cid]);
SetDParam(2, refittable ? STR_PURCHASE_INFO_REFITTABLE : STR_EMPTY);
DrawString(left, right, y, STR_PURCHASE_INFO_CAPACITY);
y += FONT_HEIGHT_NORMAL;

View File

@ -204,4 +204,9 @@ static inline bool IsCargoInClass(CargoID c, CargoClass cc)
using SetCargoBitIterator = SetBitIterator<CargoID, CargoTypes>;
/** Comparator to sort CargoID by according to desired order. */
struct CargoIDComparator {
bool operator() (const CargoID &lhs, const CargoID &rhs) const { return _sorted_cargo_types[lhs] < _sorted_cargo_types[rhs]; }
};
#endif /* CARGOTYPE_H */

View File

@ -675,10 +675,10 @@ private:
if (default_livery != nullptr) {
/* Add COLOUR_END to put the colour out of range, but also allow us to show what the default is */
default_col = (primary ? default_livery->colour1 : default_livery->colour2) + COLOUR_END;
list.emplace_back(new DropDownListColourItem(default_col, false));
list.push_back(std::make_unique<DropDownListColourItem>(default_col, false));
}
for (uint i = 0; i < lengthof(_colour_dropdown); i++) {
list.emplace_back(new DropDownListColourItem(i, HasBit(used_colours, i)));
list.push_back(std::make_unique<DropDownListColourItem>(i, HasBit(used_colours, i)));
}
byte sel = (default_livery == nullptr || HasBit(livery->in_use, primary ? 0 : 1)) ? (primary ? livery->colour1 : livery->colour2) : default_col;

View File

@ -75,14 +75,14 @@ struct SetDateWindow : Window {
case WID_SD_DAY:
for (uint i = 0; i < 31; i++) {
list.emplace_back(new DropDownListStringItem(STR_DAY_NUMBER_1ST + i, i + 1, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_DAY_NUMBER_1ST + i, i + 1, false));
}
selected = this->date.day;
break;
case WID_SD_MONTH:
for (uint i = 0; i < 12; i++) {
list.emplace_back(new DropDownListStringItem(STR_MONTH_JAN + i, i, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_MONTH_JAN + i, i, false));
}
selected = this->date.month;
break;
@ -90,7 +90,7 @@ struct SetDateWindow : Window {
case WID_SD_YEAR:
for (TimerGameCalendar::Year i = this->min_year; i <= this->max_year; i++) {
SetDParam(0, i);
list.emplace_back(new DropDownListStringItem(STR_JUST_INT, static_cast<int32_t>(i), false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_JUST_INT, static_cast<int32_t>(i), false));
}
selected = static_cast<int32_t>(this->date.year);
break;

View File

@ -876,7 +876,8 @@ struct DepotWindow : Window {
static std::string details;
details.clear();
for (CargoID cargo_type = 0; cargo_type < NUM_CARGO; cargo_type++) {
for (const CargoSpec *cs : _sorted_cargo_specs) {
CargoID cargo_type = cs->Index();
if (capacity[cargo_type] == 0) continue;
SetDParam(0, cargo_type); // {CARGO} #1

View File

@ -311,7 +311,7 @@ struct GSConfigWindow : public Window {
DropDownList list;
for (int i = config_item.min_value; i <= config_item.max_value; i++) {
list.emplace_back(new DropDownListStringItem(config_item.labels.find(i)->second, i, false));
list.push_back(std::make_unique<DropDownListStringItem>(config_item.labels.find(i)->second, i, false));
}
ShowDropDownListAt(this, std::move(list), old_val, WID_GSC_SETTING_DROPDOWN, wi_rect, COLOUR_ORANGE);

View File

@ -356,7 +356,7 @@ static DropDownList BuildMapsizeDropDown()
for (uint i = MIN_MAP_SIZE_BITS; i <= MAX_MAP_SIZE_BITS; i++) {
SetDParam(0, 1LL << i);
list.emplace_back(new DropDownListStringItem(STR_JUST_INT, i, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_JUST_INT, i, false));
}
return list;
@ -369,20 +369,20 @@ static DropDownList BuildTownNameDropDown()
/* Add and sort newgrf townnames generators */
const auto &grf_names = GetGRFTownNameList();
for (uint i = 0; i < grf_names.size(); i++) {
list.emplace_back(new DropDownListStringItem(grf_names[i], BUILTIN_TOWNNAME_GENERATOR_COUNT + i, false));
list.push_back(std::make_unique<DropDownListStringItem>(grf_names[i], BUILTIN_TOWNNAME_GENERATOR_COUNT + i, false));
}
std::sort(list.begin(), list.end(), DropDownListStringItem::NatSortFunc);
size_t newgrf_size = list.size();
/* Insert newgrf_names at the top of the list */
if (newgrf_size > 0) {
list.emplace_back(new DropDownListItem(-1, false)); // separator line
list.push_back(std::make_unique<DropDownListItem>(-1, false)); // separator line
newgrf_size++;
}
/* Add and sort original townnames generators */
for (uint i = 0; i < BUILTIN_TOWNNAME_GENERATOR_COUNT; i++) {
list.emplace_back(new DropDownListStringItem(STR_MAPGEN_TOWN_NAME_ORIGINAL_ENGLISH + i, i, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_MAPGEN_TOWN_NAME_ORIGINAL_ENGLISH + i, i, false));
}
std::sort(list.begin() + newgrf_size, list.end(), DropDownListStringItem::NatSortFunc);

View File

@ -347,12 +347,13 @@ void GfxLoadSprites()
UpdateCursorSize();
}
bool GraphicsSet::FillSetDetails(IniFile *ini, const std::string &path, const std::string &full_filename)
bool GraphicsSet::FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename)
{
bool ret = this->BaseSet<GraphicsSet, MAX_GFT, true>::FillSetDetails(ini, path, full_filename, false);
if (ret) {
IniGroup *metadata = ini->GetGroup("metadata");
IniItem *item;
const IniGroup *metadata = ini.GetGroup("metadata");
assert(metadata != nullptr); /* ret can't be true if metadata isn't present. */
const IniItem *item;
fetch_metadata("palette");
this->palette = ((*item->value)[0] == 'D' || (*item->value)[0] == 'd') ? PAL_DOS : PAL_WINDOWS;

View File

@ -274,11 +274,12 @@ HotkeyList::~HotkeyList()
* Load HotkeyList from IniFile.
* @param ini IniFile to load from.
*/
void HotkeyList::Load(IniFile *ini)
void HotkeyList::Load(const IniFile &ini)
{
IniGroup *group = ini->GetGroup(this->ini_group);
const IniGroup *group = ini.GetGroup(this->ini_group);
if (group == nullptr) return;
for (Hotkey &hotkey : this->items) {
IniItem *item = group->GetItem(hotkey.name);
const IniItem *item = group->GetItem(hotkey.name);
if (item != nullptr) {
hotkey.keycodes.clear();
if (item->value.has_value()) ParseHotkeys(hotkey, item->value->c_str());
@ -290,11 +291,11 @@ void HotkeyList::Load(IniFile *ini)
* Save HotkeyList to IniFile.
* @param ini IniFile to save to.
*/
void HotkeyList::Save(IniFile *ini) const
void HotkeyList::Save(IniFile &ini) const
{
IniGroup *group = ini->GetGroup(this->ini_group);
IniGroup &group = ini.GetOrCreateGroup(this->ini_group);
for (const Hotkey &hotkey : this->items) {
IniItem &item = group->GetOrCreateItem(hotkey.name);
IniItem &item = group.GetOrCreateItem(hotkey.name);
item.SetValue(SaveKeycodes(hotkey));
}
}
@ -320,8 +321,8 @@ int HotkeyList::CheckMatch(uint16_t keycode, bool global_only) const
static void SaveLoadHotkeys(bool save)
{
IniFile *ini = new IniFile();
ini->LoadFromDisk(_hotkeys_file, NO_DIRECTORY);
IniFile ini{};
ini.LoadFromDisk(_hotkeys_file, NO_DIRECTORY);
for (HotkeyList *list : *_hotkey_lists) {
if (save) {
@ -331,8 +332,7 @@ static void SaveLoadHotkeys(bool save)
}
}
if (save) ini->SaveToDisk(_hotkeys_file);
delete ini;
if (save) ini.SaveToDisk(_hotkeys_file);
}

View File

@ -40,8 +40,8 @@ struct HotkeyList {
HotkeyList(const std::string &ini_group, const std::vector<Hotkey> &items, GlobalHotkeyHandlerFunc global_hotkey_handler = nullptr);
~HotkeyList();
void Load(IniFile *ini);
void Save(IniFile *ini) const;
void Load(const IniFile &ini);
void Save(IniFile &ini) const;
int CheckMatch(uint16_t keycode, bool global_only = false) const;

View File

@ -1920,11 +1920,6 @@ enum CargoesFieldType {
static const uint MAX_CARGOES = 16; ///< Maximum number of cargoes carried in a #CFT_CARGO field in #CargoesField.
static bool CargoIDSorter(const CargoID &a, const CargoID &b)
{
return _sorted_cargo_types[a] < _sorted_cargo_types[b];
}
/** Data about a single field in the #IndustryCargoesWindow panel. */
struct CargoesField {
static int vert_inter_industry_space;
@ -2054,7 +2049,8 @@ struct CargoesField {
}
}
this->u.cargo.num_cargoes = (count < 0) ? static_cast<uint8_t>(insert - std::begin(this->u.cargo.vertical_cargoes)) : count;
std::sort(std::begin(this->u.cargo.vertical_cargoes), insert, &CargoIDSorter);
CargoIDComparator comparator;
std::sort(std::begin(this->u.cargo.vertical_cargoes), insert, comparator);
std::fill(insert, std::end(this->u.cargo.vertical_cargoes), CT_INVALID);
this->u.cargo.top_end = top_end;
this->u.cargo.bottom_end = bottom_end;
@ -3067,7 +3063,7 @@ struct IndustryCargoesWindow : public Window {
case WID_IC_CARGO_DROPDOWN: {
DropDownList lst;
for (const CargoSpec *cs : _sorted_standard_cargo_specs) {
lst.emplace_back(new DropDownListStringItem(cs->name, cs->Index(), false));
lst.push_back(std::make_unique<DropDownListStringItem>(cs->name, cs->Index(), false));
}
if (!lst.empty()) {
int selected = (this->ind_cargo >= NUM_INDUSTRYTYPES) ? (int)(this->ind_cargo - NUM_INDUSTRYTYPES) : -1;
@ -3081,7 +3077,7 @@ struct IndustryCargoesWindow : public Window {
for (IndustryType ind : _sorted_industry_types) {
const IndustrySpec *indsp = GetIndustrySpec(ind);
if (!indsp->enabled) continue;
lst.emplace_back(new DropDownListStringItem(indsp->name, ind, false));
lst.push_back(std::make_unique<DropDownListStringItem>(indsp->name, ind, false));
}
if (!lst.empty()) {
int selected = (this->ind_cargo < NUM_INDUSTRYTYPES) ? (int)this->ind_cargo : -1;

View File

@ -32,9 +32,9 @@
/**
* Create a new ini file with given group names.
* @param list_group_names A \c nullptr terminated list with group names that should be loaded as lists instead of variables. @see IGT_LIST
* @param list_group_names A list with group names that should be loaded as lists instead of variables. @see IGT_LIST
*/
IniFile::IniFile(const char * const *list_group_names) : IniLoadFile(list_group_names)
IniFile::IniFile(const IniGroupNameList &list_group_names) : IniLoadFile(list_group_names)
{
}
@ -56,20 +56,20 @@ bool IniFile::SaveToDisk(const std::string &filename)
std::ofstream os(OTTD2FS(file_new).c_str());
if (os.fail()) return false;
for (const IniGroup *group = this->group; group != nullptr; group = group->next) {
os << group->comment << "[" << group->name << "]\n";
for (const IniItem *item = group->item; item != nullptr; item = item->next) {
os << item->comment;
for (const IniGroup &group : this->groups) {
os << group.comment << "[" << group.name << "]\n";
for (const IniItem &item : group.items) {
os << item.comment;
/* protect item->name with quotes if needed */
if (item->name.find(' ') != std::string::npos ||
item->name[0] == '[') {
os << "\"" << item->name << "\"";
if (item.name.find(' ') != std::string::npos ||
item.name[0] == '[') {
os << "\"" << item.name << "\"";
} else {
os << item->name;
os << item.name;
}
os << " = " << item->value.value_or("") << "\n";
os << " = " << item.value.value_or("") << "\n";
}
}
os << this->comment;

View File

@ -20,18 +20,9 @@
* @param parent the group we belong to
* @param name the name of the item
*/
IniItem::IniItem(IniGroup *parent, const std::string &name) : next(nullptr)
IniItem::IniItem(const std::string &name)
{
this->name = StrMakeValid(name);
*parent->last_item = this;
parent->last_item = &this->next;
}
/** Free everything we loaded. */
IniItem::~IniItem()
{
delete this->next;
}
/**
@ -48,37 +39,9 @@ void IniItem::SetValue(const std::string_view value)
* @param parent the file we belong to
* @param name the name of the group
*/
IniGroup::IniGroup(IniLoadFile *parent, const std::string &name) : next(nullptr), type(IGT_VARIABLES), item(nullptr)
IniGroup::IniGroup(const std::string &name, IniGroupType type) : type(type)
{
this->name = StrMakeValid(name);
this->last_item = &this->item;
*parent->last_group = this;
parent->last_group = &this->next;
if (parent->list_group_names != nullptr) {
for (uint i = 0; parent->list_group_names[i] != nullptr; i++) {
if (this->name == parent->list_group_names[i]) {
this->type = IGT_LIST;
return;
}
}
}
if (parent->seq_group_names != nullptr) {
for (uint i = 0; parent->seq_group_names[i] != nullptr; i++) {
if (this->name == parent->seq_group_names[i]) {
this->type = IGT_SEQUENCE;
return;
}
}
}
}
/** Free everything we loaded. */
IniGroup::~IniGroup()
{
delete this->item;
delete this->next;
}
/**
@ -86,10 +49,10 @@ IniGroup::~IniGroup()
* @param name name of the item to find.
* @return the requested item or nullptr if not found.
*/
IniItem *IniGroup::GetItem(const std::string &name) const
const IniItem *IniGroup::GetItem(const std::string &name) const
{
for (IniItem *item = this->item; item != nullptr; item = item->next) {
if (item->name == name) return item;
for (const IniItem &item : this->items) {
if (item.name == name) return &item;
}
return nullptr;
@ -102,12 +65,22 @@ IniItem *IniGroup::GetItem(const std::string &name) const
*/
IniItem &IniGroup::GetOrCreateItem(const std::string &name)
{
for (IniItem *item = this->item; item != nullptr; item = item->next) {
if (item->name == name) return *item;
for (IniItem &item : this->items) {
if (item.name == name) return item;
}
/* Item doesn't exist, make a new one. */
return *(new IniItem(this, name));
return this->CreateItem(name);
}
/**
* Create an item with the given name. This does not reuse an existing item of the same name.
* @param name name of the item to create.
* @return the created item.
*/
IniItem &IniGroup::CreateItem(const std::string &name)
{
return this->items.emplace_back(name);
}
/**
@ -116,22 +89,7 @@ IniItem &IniGroup::GetOrCreateItem(const std::string &name)
*/
void IniGroup::RemoveItem(const std::string &name)
{
IniItem **prev = &this->item;
for (IniItem *item = this->item; item != nullptr; prev = &item->next, item = item->next) {
if (item->name != name) continue;
*prev = item->next;
/* "last_item" is a pointer to the "real-last-item"->next. */
if (this->last_item == &item->next) {
this->last_item = prev;
}
item->next = nullptr;
delete item;
return;
}
this->items.remove_if([&name](const IniItem &item) { return item.name == name; });
}
/**
@ -139,81 +97,85 @@ void IniGroup::RemoveItem(const std::string &name)
*/
void IniGroup::Clear()
{
delete this->item;
this->item = nullptr;
this->last_item = &this->item;
this->items.clear();
}
/**
* Construct a new in-memory Ini file representation.
* @param list_group_names A \c nullptr terminated list with group names that should be loaded as lists instead of variables. @see IGT_LIST
* @param seq_group_names A \c nullptr terminated list with group names that should be loaded as lists of names. @see IGT_SEQUENCE
* @param list_group_names A list with group names that should be loaded as lists instead of variables. @see IGT_LIST
* @param seq_group_names A list with group names that should be loaded as lists of names. @see IGT_SEQUENCE
*/
IniLoadFile::IniLoadFile(const char * const *list_group_names, const char * const *seq_group_names) :
group(nullptr),
IniLoadFile::IniLoadFile(const IniGroupNameList &list_group_names, const IniGroupNameList &seq_group_names) :
list_group_names(list_group_names),
seq_group_names(seq_group_names)
{
this->last_group = &this->group;
}
/** Free everything we loaded. */
IniLoadFile::~IniLoadFile()
{
delete this->group;
}
/**
* Get the group with the given name. If it doesn't exist
* and \a create_new is \c true create a new group.
* Get the group with the given name.
* @param name name of the group to find.
* @param create_new Allow creation of group if it does not exist.
* @return The requested group if it exists or was created, else \c nullptr.
* @return The requested group or \c nullptr if not found.
*/
IniGroup *IniLoadFile::GetGroup(const std::string &name, bool create_new)
const IniGroup *IniLoadFile::GetGroup(const std::string &name) const
{
/* does it exist already? */
for (IniGroup *group = this->group; group != nullptr; group = group->next) {
if (group->name == name) return group;
for (const IniGroup &group : this->groups) {
if (group.name == name) return &group;
}
if (!create_new) return nullptr;
return nullptr;
}
/* otherwise make a new one */
IniGroup *group = new IniGroup(this, name);
group->comment = "\n";
return group;
/**
* Get the group with the given name.
* @param name name of the group to find.
* @return The requested group or \c nullptr if not found.
*/
IniGroup *IniLoadFile::GetGroup(const std::string &name)
{
for (IniGroup &group : this->groups) {
if (group.name == name) return &group;
}
return nullptr;
}
/**
* Get the group with the given name, and if it doesn't exist create a new group.
* @param name name of the group to find.
* @return the requested group.
*/
IniGroup &IniLoadFile::GetOrCreateGroup(const std::string &name)
{
for (IniGroup &group : this->groups) {
if (group.name == name) return group;
}
/* Group doesn't exist, make a new one. */
return this->CreateGroup(name);
}
/**
* Create an group with the given name. This does not reuse an existing group of the same name.
* @param name name of the group to create.
* @return the created group.
*/
IniGroup &IniLoadFile::CreateGroup(const std::string &name)
{
IniGroupType type = IGT_VARIABLES;
if (std::find(this->list_group_names.begin(), this->list_group_names.end(), name) != this->list_group_names.end()) type = IGT_LIST;
if (std::find(this->seq_group_names.begin(), this->seq_group_names.end(), name) != this->seq_group_names.end()) type = IGT_SEQUENCE;
return this->groups.emplace_back(name, type);
}
/**
* Remove the group with the given name.
* @param name name of the group to remove.
*/
void IniLoadFile::RemoveGroup(const char *name)
void IniLoadFile::RemoveGroup(const std::string &name)
{
size_t len = strlen(name);
IniGroup *prev = nullptr;
IniGroup *group;
/* does it exist already? */
for (group = this->group; group != nullptr; prev = group, group = group->next) {
if (group->name.compare(0, len, name) == 0) {
break;
}
}
if (group == nullptr) return;
if (prev != nullptr) {
prev->next = prev->next->next;
if (this->last_group == &group->next) this->last_group = &prev->next;
} else {
this->group = this->group->next;
if (this->last_group == &group->next) this->last_group = &this->group;
}
group->next = nullptr;
delete group;
size_t len = name.length();
this->groups.remove_if([&name, &len](const IniGroup &group) { return group.name.compare(0, len, name) == 0; });
}
/**
@ -224,7 +186,7 @@ void IniLoadFile::RemoveGroup(const char *name)
*/
void IniLoadFile::LoadFromDisk(const std::string &filename, Subdirectory subdir)
{
assert(this->last_group == &this->group);
assert(this->groups.empty());
char buffer[1024];
IniGroup *group = nullptr;
@ -275,7 +237,7 @@ void IniLoadFile::LoadFromDisk(const std::string &filename, Subdirectory subdir)
e--;
}
s++; // skip [
group = new IniGroup(this, std::string(s, e - s));
group = &this->CreateGroup(std::string(s, e - s));
if (comment_size != 0) {
group->comment.assign(comment, comment_size);
comment_size = 0;
@ -283,9 +245,9 @@ void IniLoadFile::LoadFromDisk(const std::string &filename, Subdirectory subdir)
} else if (group != nullptr) {
if (group->type == IGT_SEQUENCE) {
/* A sequence group, use the line as item name without further interpretation. */
IniItem *item = new IniItem(group, std::string(buffer, e - buffer));
IniItem &item = group->CreateItem(std::string(buffer, e - buffer));
if (comment_size) {
item->comment.assign(comment, comment_size);
item.comment.assign(comment, comment_size);
comment_size = 0;
}
continue;
@ -301,9 +263,9 @@ void IniLoadFile::LoadFromDisk(const std::string &filename, Subdirectory subdir)
}
/* it's an item in an existing group */
IniItem *item = new IniItem(group, std::string(s, t - s));
IniItem &item = group->CreateItem(std::string(s, t - s));
if (comment_size != 0) {
item->comment.assign(comment, comment_size);
item.comment.assign(comment, comment_size);
comment_size = 0;
}
@ -320,9 +282,9 @@ void IniLoadFile::LoadFromDisk(const std::string &filename, Subdirectory subdir)
/* If the value was not quoted and empty, it must be nullptr */
if (!quoted && e == t) {
item->value.reset();
item.value.reset();
} else {
item->value = StrMakeValid(std::string(t));
item.value = StrMakeValid(std::string(t));
}
} else {
/* it's an orphan item */

View File

@ -21,48 +21,48 @@ enum IniGroupType {
/** A single "line" in an ini file. */
struct IniItem {
IniItem *next; ///< The next item in this group
std::string name; ///< The name of this item
std::optional<std::string> value; ///< The value of this item
std::string comment; ///< The comment associated with this item
IniItem(struct IniGroup *parent, const std::string &name);
~IniItem();
IniItem(const std::string &name);
void SetValue(const std::string_view value);
};
/** A group within an ini file. */
struct IniGroup {
IniGroup *next; ///< the next group within this file
std::list<IniItem> items; ///< all items in the group
IniGroupType type; ///< type of group
IniItem *item; ///< the first item in the group
IniItem **last_item; ///< the last item in the group
std::string name; ///< name of group
std::string comment; ///< comment for group
IniGroup(struct IniLoadFile *parent, const std::string &name);
~IniGroup();
IniGroup(const std::string &name, IniGroupType type);
IniItem *GetItem(const std::string &name) const;
const IniItem *GetItem(const std::string &name) const;
IniItem &GetOrCreateItem(const std::string &name);
IniItem &CreateItem(const std::string &name);
void RemoveItem(const std::string &name);
void Clear();
};
/** Ini file that only supports loading. */
struct IniLoadFile {
IniGroup *group; ///< the first group in the ini
IniGroup **last_group; ///< the last group in the ini
using IniGroupNameList = std::initializer_list<std::string_view>;
std::list<IniGroup> groups; ///< all groups in the ini
std::string comment; ///< last comment in file
const char * const *list_group_names; ///< nullptr terminated list with group names that are lists
const char * const *seq_group_names; ///< nullptr terminated list with group names that are sequences.
const IniGroupNameList list_group_names; ///< list of group names that are lists
const IniGroupNameList seq_group_names; ///< list of group names that are sequences.
IniLoadFile(const char * const *list_group_names = nullptr, const char * const *seq_group_names = nullptr);
virtual ~IniLoadFile();
IniLoadFile(const IniGroupNameList &list_group_names = {}, const IniGroupNameList &seq_group_names = {});
virtual ~IniLoadFile() { }
IniGroup *GetGroup(const std::string &name, bool create_new = true);
void RemoveGroup(const char *name);
const IniGroup *GetGroup(const std::string &name) const;
IniGroup *GetGroup(const std::string &name);
IniGroup &GetOrCreateGroup(const std::string &name);
IniGroup &CreateGroup(const std::string &name);
void RemoveGroup(const std::string &name);
void LoadFromDisk(const std::string &filename, Subdirectory subdir);
@ -86,7 +86,7 @@ struct IniLoadFile {
/** Ini file that supports both loading and saving. */
struct IniFile : IniLoadFile {
IniFile(const char * const *list_group_names = nullptr);
IniFile(const IniGroupNameList &list_group_names = {});
bool SaveToDisk(const std::string &filename);

View File

@ -4422,7 +4422,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... te n
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... te naby aan 'n ander dorp
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... te veel dorpe
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... daar is nie meer spasie oor op die kaart nie
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE} Die dorp sal nie paaie bou nie. Jy kan dit verander deur die bou van paaie via Stellings-> Omgewings-> Dorpe te aktiveer
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Pad werke in verloop
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Kan nie die dorp verwyder nie...{}'n Stasie of depot verwys na die dorp of die blok wat deur die dorp besit word kan nie verwyder word nie.
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... daar is geen plek vir 'n standbeeld in die middel van die dorp

View File

@ -4137,7 +4137,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... قر
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... قريبة جدا من مدينة أخرى
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... المدن كثيرة جدا
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... لا يوجد فراغ في الخريطة
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}لن تبني البلدية طرق جديدة. بإمكانك تمكين بناء الطرق الجديدة عن طريق الاعدادات --> البيئة--> المدن
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}اعمال الطرق قيد التنفيذ
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}لا يمكن ازالة هذه المدينة{}محطة او ورشة مرتبطة بالمدينة او هناك مربع مملوك للمدينة لا يمكن لزالته
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... لا يوجد مكان مناسب للمجسم بداخل هذة المدينة/البلدة

View File

@ -4171,7 +4171,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... mapa
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... beste herritik hurbilegi
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... herri gehiegi
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... ez dago leku gehiagorik mapan
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Herriak ez du errepiderik eraikiko. Herriek errepideak eraiki ahal izateko Ezarpen Aurreratuak->Ekonomia->Herriak
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Errepide lanak egiten
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Geltoki edo gordailu bat herriari lotua dago edo ezin izan da herriaren jabegoa den lauki bat ezabatu
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... ez dago leku egokirik estatua batentzat hiri honen erdian

View File

@ -4778,7 +4778,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... за
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... занадта блізка да іншага горада
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... занадта шмат гарадоў
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... няма месца на мапе
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Гарады ня будуць будаваць дарогі самі. Вы можаце ўключыць будаўніцтва дарог у раздзеле «Наладкі -> Навак.{NBSP}асяроддзе -> Гарады».
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Ідуць дарожныя работы...
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Немагчыма зьнішчыць горад:{}да яго адносіцца станцыя або дэпо, альбо немагчыма ачысьціць адну з занятых ім клетак.
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... у цэнтры горада няма месца для статуі

View File

@ -4867,7 +4867,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... muit
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... muito perto de outra cidade
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... cidades demais
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... não há mais espaço no mapa
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}A cidade não irá construir estradas. Você pode ativar a construção através de Configurações->Ambiente->Cidades
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Recapeamento rodoviário em progresso
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Impossível remover cidade...{}Uma estação ou depósito referente à essa cidade não pode ser removido
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... não há local para uma estátua no centro dessa cidade

View File

@ -4251,7 +4251,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... пр
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... прекалено близо до друг град
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... прекалено много градове
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... няма повече място на картата
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Градът няма да изгражда пътища. Можете да активирате строенето на пътища чрез Настройки за напреднали->Икономика->Градове.
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Пътни ремонти в процес
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Градът не може да бъде премахнат...{}Станция или депо има връзка с града, или плочка, собственост на града, не може да бъде отстранена
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... няма подходящо място за статуя в центъра на града

View File

@ -4867,7 +4867,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... mass
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... massa prop d'una altra població
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... massa poblacions
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}...no queda espai al mapa.
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}La població no construirà carrers. Pots activar la construcció de carrers via Configuració->Interacció amb l'entorn->Poblacions
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Obres en progrés
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}No es pot eliminar aquesta població...{}Hi ha una estació, un dipòsit o una cel·la pertanyent a la població que no pot ser eliminada
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... no hi ha un lloc adequat per situar l'estàtua al centre d'aquesta població

View File

@ -4609,7 +4609,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... preb
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... preblizu drugome gradu
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... previše gradova
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... nema više mjesta na karti
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Grad neće graditi ceste. Možete uključiti gradnju cesta putem Postavki->Okolina->Gradovi
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Cestovni radovi u tijeku
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Nije moguće izbrisati ovaj grad...{}Postaja ili spremište se pozivaju na grad ili polja u vlasništvu grada nije moguće ukloniti
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... nema odgovarajućeg mjesta za kip u središtu ovog grada

View File

@ -4878,7 +4878,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... moc
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... moc blízko k jinému městu
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... příliš mnoho měst
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... na mapě už není místo
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Město nebude stavět silnice. Můžete to změnit přes Pokročilé nastavení->Ekonomika->Města
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Silnice je v rekonstrukci
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Nelze vybourat město...{}Buď k němu patří stanice nebo depo, anebo se nedá odklidit políčko městem vlastněné
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... v tomto městě není žádné místo vhodné pro umístění sochy

View File

@ -4866,7 +4866,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... for
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... for tæt på en anden by
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... for mange byer
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... der er ikke mere plads på kortet
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Byen vil ikke kunne bygge veje. Du kan tillade byer at bygge veje via Avancerede indstillinger->Økonomi->Byer.
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Vejarbejde i gang
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Kan ikke slette denne by...{}En station eller et depot refererer til byen, eller en brik der er ejet a byen kan ikke fjernes
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... Der er ingen egnede steder at placere en statue

View File

@ -4866,7 +4866,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... te d
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... te dicht bij een andere plaats
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... te veel plaatsen
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... er is geen ruimte meer op de kaart
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}De stad bouwt geen wegen. Het bouwen van wegen kan aangezet worden via Instellingen->Omgeving->Steden
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Wegwerkzaamheden in uitvoering
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Kan deze stad niet verwijderen...{}Een station of depot verwijst naar deze plaats of een door de stad beheerde tegel kan niet worden verwijderd
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... er is geen geschikte plaats voor een standbeeld in het centrum van dit dorp

View File

@ -924,10 +924,8 @@ STR_NEWS_NEW_VEHICLE_NOW_AVAILABLE_WITH_TYPE :{BLACK}New {STR
STR_NEWS_SHOW_VEHICLE_GROUP_TOOLTIP :{BLACK}Open the group window focused on the vehicle's group
STR_NEWS_STATION_NO_LONGER_ACCEPTS_CARGO :{WHITE}{STATION} no longer accepts {STRING}
STR_NEWS_STATION_NO_LONGER_ACCEPTS_CARGO_OR_CARGO :{WHITE}{STATION} no longer accepts {STRING} or {STRING}
STR_NEWS_STATION_NOW_ACCEPTS_CARGO :{WHITE}{STATION} now accepts {STRING}
STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO :{WHITE}{STATION} now accepts {STRING} and {STRING}
STR_NEWS_STATION_NO_LONGER_ACCEPTS_CARGO_LIST :{WHITE}{STATION} no longer accepts: {CARGO_LIST}
STR_NEWS_STATION_NOW_ACCEPTS_CARGO_LIST :{WHITE}{STATION} now accepts: {CARGO_LIST}
STR_NEWS_OFFER_OF_SUBSIDY_EXPIRED :{BIG_FONT}{BLACK}Offer of subsidy expired:{}{}{STRING} from {STRING2} to {STRING2} will now not attract a subsidy
STR_NEWS_SUBSIDY_WITHDRAWN_SERVICE :{BIG_FONT}{BLACK}Subsidy withdrawn:{}{}{STRING} service from {STRING2} to {STRING2} is no longer subsidised

View File

@ -4866,7 +4866,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... too
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... too close to another town
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... too many towns
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... there is no more space on the map
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}The town will not build roads. You can enable building of roads via Advanced Settings->Environment->Towns
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Road works in progress
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Can't delete this town...{}A station or depot is referring to the town or a town owned tile can't be removed
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... there is no suitable place for a statue in the centre of this town

View File

@ -4866,7 +4866,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... too
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... too close to another town
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... too many towns
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... there is no more space on the map
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}The town will not build roads. You can enable building of roads via Settings->Environment->Towns
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Road work in progress
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Can't delete this town...{}A station or depot is referring to the town or a town owned tile can't be removed
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... there is no suitable place for a statue in the center of this town

View File

@ -4768,7 +4768,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... tro
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... tro proksime al alia urbo
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... tro da urboj
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... spaco mankas sur la mapo
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}La urbo ne konstruos stratojn. Vi povas ebligi stratkonstruadon per Avancitaj Agordoj->Ekonomio->Urboj
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Aktivas vojprilaborado
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Ne eblas forviŝi ĉi tiun urbon...{}Stacidomo aŭ garaĝo havas referencon al la urbo, aŭ ne eblas forviŝi kahelon posedatan de la urbo
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... ne jen estas konvenan lokon por statuo en la centro de ĉi tiu urbo

View File

@ -4820,7 +4820,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... liig
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... liiga lähedal teisele asulale
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... liiga palju asulaid
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... pole enam ruumi kaardil
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Asula ei ehita teid. Teedeehituse lubamiseks Põhjalik seadistus->Majandus->Asulad
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Teede ehitamine
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Seda asulat ei saa kõrvaldada...{}Jaam või depoo viitab asulale, või asulale kuuluvat ruutu ei saa kõrvaldada
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... asula keskuses ei leidu kujule sobivat kohta

View File

@ -3826,7 +3826,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... ov t
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... ov tætt við eina aðra bygd
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... ov nógvar bygdir
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... tað er einki pláss eftir á kortinum
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Bygdin byggir ikki vegir. Tú kanst tendra vega byggjing í Víðkaðir Innstillingar->Búðskapur->Bygdir
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Veg arbeiði í gongd
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Kann ikki strika hesa bygdina...{}Ein støð ella goymsla vísur til bygdina, ella ein puntur ið er ogn hjá bygdini kann ikki beinast burtur
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... einki hóskandi stað til eina standmynd í miðjuni av hesi bygdini

View File

@ -4866,7 +4866,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... liia
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... liian lähellä toista kuntaa
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... liian monta kuntaa
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... kartalla ei ole enää tilaa
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Kunta ei rakenna teitä. Voit sallia teiden rakentamisen valikosta Asetukset->Ympäristö->Kunnat
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Tietyöt ovat käynnissä.
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Kuntaa ei voida poistaa...{}Asema tai varikko viittaa kuntaan tai kunnan omistamaa ruutua ei voida poistaa
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... tämän kunnan keskustassa ei ole sopivaa paikkaa patsaalle

View File

@ -4867,7 +4867,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... trop
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... trop près d'une autre ville
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... trop de villes
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... il n'y a plus d'emplacement sur la carte
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}La ville ne construira pas de routes. Vous pouvez activer la construction des routes sous Paramètres->Environnement->Villes
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Route en travaux
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Impossible de supprimer cette ville...{}Une station ou un dépôt fait référence à cette ville ou une propriété municipale ne peut pas être supprimée.
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... aucun emplacement convenable disponible pour une statue dans ce centre-ville

View File

@ -4565,7 +4565,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... ro f
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... ro fhaisg air baile eile
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... tha cus bhailtean ann
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... chan eil rum air fhàgail air a' mhapa
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Cha tog am baile rathad sam bith. S urrainn dhut togail rathaidean a chur an comas le Roghainnean->Àrainneachd->Bailtean
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Rathad ga ath-thogail
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Cha ghabh am baile seo sguabadh às...{}Tha stèisean no port no garaids no trèan-lann no cala no hangar a' toirt iomradh air a' bhaile no tha leac ann a tha leis a' bhaile is nach gabh toirt air falbh
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... chan eil ionad freagarrach airson ìomhaigh ann am meadhan a' bhaile seo

View File

@ -4812,7 +4812,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... dema
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... demasiado preto doutra cidade
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... hai demasiadas cidades
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... non queda máis espazo no mapa
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}O pobo non construirá estradas. Podes activar a función de construción de estradas en Opcións Avanzadas->Economía->Pobos
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Obras na estrada en curso
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Non se pode borrar esta vila...{}Unha estación ou depósito está relacionado coa vila ou un cadro propiedade da vila non pode ser eliminado
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... non hai ningún sitio adecuado para unha estatua no centro desta vila

View File

@ -4843,7 +4843,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... zu d
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... zu dicht an einer anderen Stadt
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... zu viele Städte
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... es ist kein Platz mehr auf dem Spielfeld
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Städte bauen im Moment keine Straßen. Städtischer Straßenbau kann mittels Einstellungen->Umgebung->Städte eingestellt werden
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Straßenarbeiten sind im Gange
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Stadt kann nicht gelöscht werden ...{}Eine Station oder ein Depot bezieht sich auf diese Stadt oder ein Feld im städtischen Besitz kann nicht entfernt werden.
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... es gibt keinen geeigneten Standort für die Statue im Zentrum dieser Stadt

View File

@ -4865,7 +4865,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... πο
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... πολύ κοντά σε άλλη πόλη
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... πάρα πολλές πόλεις
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... δεν υπάρχει άλλος χώρος στον χάρτη
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Η πόλη δεν θα οικοδομεί δρόμους. Μπορείτε να ενεργοποιήσετε την κατασκευή οδών μέσω τις Προχωρημένες Επιλογές->Οικονομία->Πόλεις
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Έργα οδοποιίας σε εξέλιξη
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Δεν γίνεται να διαγραφεί η πόλη...{}Ένας σταθμός ή ένα αμαξοστάσιο που αναφέρεται στην πόλη ή ένα τετραγωνίδιο της πόλης δεν μπορεί να αφαιρεθεί
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... δεν υπάρχει κατάλληλο μέρος για άγαλμα στο κέντρο αυτής της πόλης

View File

@ -4468,7 +4468,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... קר
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... קרוב מידי לעיר אחרת
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... יותר מידי ערים
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... אין יותר מקום על המפה
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}העיר לא תבנה כבישים. באפשרותך לאפשר בניית כבישים בעזרת תפריט הגדרות מתקמדות->כלכלה->ערים
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}עבודות כביש בפעולה
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}לא ניתן למחוק עיר זו...{}תחנה או מוסך מקושר לעיר או שמשבצת בבעלות העיר לא ניתנת להסרה
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... אין אף מיקום מתאים לפסל במרכז עיירה זו

View File

@ -4909,7 +4909,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... túl
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... túl közel van egy másik településhez
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... túl sok a település
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... nincs több hely a térképen
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}A település nem fog utakat építeni. Az útépítést a Haladó beállítások->Környezet->Települések menüben engedélyezheted
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Útkarbantartás folyamatban
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Nem törölheted ezt a várost...{}Egy állomás vagy járműtelep hivatkozik a városra, vagy egy városi tulajdonú mező nem eltávolítható
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... nincs megfelelő hely egy szobornak a város központjában

View File

@ -4059,7 +4059,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... of n
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... of nálægt öðrum bæ
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... of margir bæir
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... það er ekkert laust svæði á kortinu
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Bærinn getur ekki lagt vegi. Því er hægt að breyta í Ítarlegar stillingar->Efnahagur->Bæir.
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Vegaframkvæmdir standa yfir
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Ekki hægt að eyða bæ...{}Stöð eða skýli vísar í þennan bæ eða ekki hægt að fjarlægja reit í eigu bæjarins.
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... það er enginn ákjósanlegur staður fyrir styttu í miðju þessa bæjar

View File

@ -4813,7 +4813,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... terl
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... terlalu dekat dengan kota lain
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... terlalu banyak kota
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... tidak ada lagi ruang tersisa dalam peta
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Kota tidak akan membangun jalan. Anda dapat mengaktifkan pembangunan jalan pada menu Pengaturan Lanjutan->Ekonomi->Kota
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Jalan sedang dikerjakan
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Tidak dapat menghancurkan kota ini...{}Suatu stasiun atau depo tergantung pada kota ini atau kotak milik kota tidak dapat dihapus
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... tidak ada tempat yang cocok untuk patung di tengah kota ini

View File

@ -4670,7 +4670,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... rogh
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... roghearr do bhaile eile
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... an iomarca bailte
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... níl a thuilleadh spáis ar an léarscáil
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Ní thógfaidh an baile seo bóithre. Is féidir leat tógáil bóithre a chumasú in Ardsocruithe->Geilleagar->Bailte.
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Tá oibreacha bóthair ar bun
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Ní féidir an baile seo a scriosadh...{}Ní féidir stáisiún nó iosta atá ag tagairt don bhaile nó do thíle atá faoi úinéireacht an bhaile a bhaint
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... níl aon suíomh oiriúnach do dhealbh i lár an bhaile seo

View File

@ -4907,7 +4907,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... trop
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... troppo vicino ad un'altra città
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... troppe città
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... non c'è altro spazio sulla mappa
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Alla città non è permesso costruire strade. È possibile abilitare la costruzione di strade in Impostazioni -> Ambiente -> Città
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Lavori stradali in corso
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Impossibile eliminare la città...{}Una stazione o un deposito fa ancora riferimento alla città o una casella di proprietà della città non può essere rimossa
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... non ci sono spazi adeguati per una statua nel centro di questa città

View File

@ -4791,7 +4791,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}マッ
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}他の街に近すぎます
STR_ERROR_TOO_MANY_TOWNS :{WHITE}街数の制限を超えています
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}マップに空きスペースがありません
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}この街は自動では道路を敷設しません。「設定→環境→街」から道路の敷設を許可できます
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}道路補修工事中です
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}街を削除できません{}この街名を参照する停留施設・車庫か、街が所有するタイルが除去できません
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}街の中心部に像を建てるのに適した場所がありません

View File

@ -4867,7 +4867,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... 지
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... 다른 도시와 너무 가깝습니다
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... 도시가 너무 많습니다
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... 지도에 더 이상 공간이 없습니다
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}도시가 도로를 짓지 않을 것입니다. [설정→환경→도시]에서 도로를 지을 수 있도록 설정을 변경하실 수 있습니다.
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}도로 작업이 진행 중입니다
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}이 도시를 삭제할 수 없습니다...{}도시나 도시 소유의 땅에 역, 정류장, 항구, 공항 또는 차량기지, 차고지, 정박소 등이 존재하면 도시를 삭제할 수 없습니다.
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... 이 도시의 중심에 동상을 세우기 적합한 장소가 없습니다

View File

@ -4558,7 +4558,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... nimi
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... nimis prope aliud oppidum
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... nimis oppida adsunt
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... plus spatium tabulae deest
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Oppidum non vias struet. Potes hanc optionem mutare in Electionibus->Circumiecta->Oppida
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Constructio viaria agitur
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Non licet oppidum delere...{}Statio receptaculumve est oppido sive non licet tegulam oppidi removere
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... non est locus effigiei idoneus in medio oppidi

View File

@ -4769,7 +4769,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... pār
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... pārāk tuvu citai pilsētai
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... pārāk daudz pilsētu
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... uz kartes nav vairāk vietas
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Pilsēta ceļus nebūvēs. Jūs varat ieslēgt ceļu būvi caur Papildu iestatījumi->Ekonomika->Pilsētas
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Notiek ceļa remonts
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Šo pilsētu nevar dzēst...{}Kāda stacija vai depo attiecas uz pilsētu. Vai pilsētai pieder nenoņemams lauciņš
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... šās pilsētas centrā statujai nav piemērotas vietas

View File

@ -4964,7 +4964,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... per
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... per arti kito miesto
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... per daug miestų
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... daugiau nera vietos zemelapyje
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Miestas nestatys kelių. Jūs galite įjungti kelių statybą per „Išplėstinės nuostatos>Aplinka>Miestai“.
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Vyksta kelio darbai
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Negalima panaikinti šio miesto...{}Mieste yra stotelė arba depas, arba miestui priklausantis vienas iš laukelių negali būti pašalintas
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... nėra tinkamos vietos statulai šio miesto centre

View File

@ -4762,7 +4762,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... ze n
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... ze no un enger anerer Stad
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... ze vill Stied
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... et ass keng Plaz méi op der Kaart
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Stied bauen keng Stroossen. Du kanns de Bau iwwert Astellungen->Economie->Stied aschalten
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Stroossenarbeschten amgaangen
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Kann des Stad net läschen...{}Eng Statioun oder Schapp huet den Numm vun dëser Stad oder en Stéck dat der Stad gehéiert kann net ewechgeholl ginn
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... et gëtt keng gëeegent Plaz fir eng Statu am Stadzentrum

View File

@ -3965,7 +3965,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... terl
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... terlalu hampir ke bandar lain
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... bandar terlalu banyak
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... ruang tidak mencukupi di dalam peta
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Bandar ini tidak akan membina jalan. Anda boleh membenarkan pembinaan jalan melalui Tetapan Lanjutan->Ekonomi->Bandar
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Kerja-kerja jalanraya sedang berjalan
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Tidak boleh padam bandar ini...{}Tidak boleh dipadamkan kerana terdapat sebuah stesen atau depoh yang dipunyai bandar atau petak bandar
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... tiada lokasi sesuai untuk arca di tengah bandar

View File

@ -4692,7 +4692,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}...{NBSP
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}...{NBSP}for nær en annen by
STR_ERROR_TOO_MANY_TOWNS :{WHITE}...{NBSP}for mange byer
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... det er ikke mer plass på kartet
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Byen kommer ikke til å bygge veier. Du kan aktivere bygging av veier via Innstillinger->Miljø->Byer
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Veiarbeid i gang
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Kan ikke fjerne denne byen...{}En stasjon eller garasje/stall/hangar/dokk henviser til byen eller en by-eid rute som ikke kan fjernes
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... det er ingen passende steder for en statue i sentrum av denne byen

View File

@ -4194,7 +4194,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... for
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... for nær ein annan by
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... for mange byar
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... det er ikkje meir plass på kartet
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Byen byggjer ikkje vegar. Du kan tillete veg-bygging i Avanserte innstillingar -> Økonomi -> Byar
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Vegarbeid pågår
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Kan ikkje fjerne denne byen...{}Ein stasjon eller garasje/stall/hangar/dokk refererar til byen eller ei by-egd rute som ikkje kan fjernast
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... det er ingen passande plass til statue i sentrum av denne byen

View File

@ -5252,7 +5252,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... zbyt
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... zbyt blisko innego miasta
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... zbyt wiele miast
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... nie ma więcej miejsca na mapie
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Miasto nie będzie budować dróg. Możesz zezwolić na budowę dróg poprzez Ustawienia->Środowisko->Miasta
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Trwają roboty drogowe
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Nie można usunąć tego miasta...{}Stacja lub zajezdnia przynależy do tego miasta lub obszar miasta nie może być usunięty
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... w centrum tego miasta nie ma odpowiedniego miejsca na pomnik

View File

@ -4867,7 +4867,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... muit
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... muito perto de outra localidade
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... demasiadas localidades
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... não existe mais espaço no mapa
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}A localidade não construirá estradas. Pode-se permitir a construção de estradas por Opções Avançadas->Economia->Localidades
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Trabalhos na estrada em curso
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Não é possível eliminar esta localidade...{}Uma estação ou depósito refere-se à localidade ou não é possível remover terreno pertencente à mesma
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... não há um sítio adequado para uma estátua no centro desta localidade

View File

@ -4865,7 +4865,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... prea
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... prea aproape de alt oraş
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... prea multe oraşe
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... nu mai este loc pe hartă
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Orașul nu va construi drumuri. Poți activa construirea drumurilor din Setări avansate -> Economie -> Orașe
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Lucrari la drum in curs de desfasurare
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Acest oraș nu poate fi șters...{}O stație sau un depou face referire la acest oraș, sau o parcelă deținută de oraș nu poate fi eliminată
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... nu există niciun loc potrivit pentru o statuie în centrul acestui oraș

View File

@ -5053,7 +5053,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... сл
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... слишком близко к другому городу
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... слишком много городов
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... нет места на карте
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Города не будут строить дороги сами. Вы можете включить строительство дорог в разделе «Настройки -> Окр.{NBSP}среда -> Города».
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Идут дорожные работы...
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Невозможно уничтожить город:{}к нему относится станция или депо, либо невозможно очистить одну из занимаемых им клеток.
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... в центре города нет места для статуи

View File

@ -4963,7 +4963,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... prev
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... drugo naselje je previše blizu
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... ima previše naselja
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... više ne postoji slobodnog prostora na terenu
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Naselje neće graditi kolovoze. Možete uključiti gradnju kolovoza preko Napredna Podešavanja->Okruženje->Naselja
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Putni radovi u toku
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Nije moguće obrisati naselje...{}Stanica ili depo na zemljištvu naselja se ne može ukloniti
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... ne postoji odgovarajuće mesto za spomenik u centru ovog naselja

View File

@ -4866,7 +4866,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}太靠
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}太靠近另一个城镇了
STR_ERROR_TOO_MANY_TOWNS :{WHITE}城镇太多了
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}地图上没有多余的地方了
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}城镇不会修建道路{}您可以在“设置->环境->城镇”选项下开启建设道路的功能
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}正在进行道路工程
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}无法删除城镇...{}城镇范围内还有车站、车库或无法移除的区块
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... 城市中心没有合适的地方放置公司塑像

View File

@ -4880,7 +4880,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... prí
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... príliš blízko iného mesta
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... príliš veľa miest
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... nie je miesto na mape
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Mesto nebude stavať cesty. Môžete povoliť budovanie ciest cez Pokročilé nasvavenia->Ekonomika->Mestá.
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Prebiehajú cestné práce
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Toto mesto nie je možné odstrániť...{}Stanica alebo depo sa odvoláva na mesto, alebo parcela vo vlastníctve mesta nemôže byť odstránená
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... v centre mesta sa nenachádza žiadne vhodné miesto pre sochu

View File

@ -4447,7 +4447,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... preb
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... preblizu drugemu mestu
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... preveliko število mest
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... ni več prostora na zemljevidu
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Mesta ne bodo gradila cest. Lahko omogočiš gradnjo cest v Napredne nastavitve->Ekonomija->Mesta
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Cestna dela napredujejo
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Ni mogoče zbrisati mesta...{}Postaja ali garaža se nanaša na to mesto ali pa področje v lastnini mesta ne more biti odstranjeno
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... ni primernega mesta za kip v centru tega mesta

View File

@ -4759,7 +4759,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... dema
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... demasiado cerca de otro municipio
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... demasiados municipios
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... no hay más espacio en el mapa
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}El municipio no construirá carreteras. Puedes activar la función de construcción de carreteras en Configuración->Ambiente->Municipios
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Obras de carretera en progreso
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}No se puede borrar este municipio...{}Quedan estaciones o depósitos relacionados con él, o una propiedad suya no puede ser retirada
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... no existe un lugar apropiado para una estatua en el centro de este municipio

View File

@ -4760,7 +4760,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... dema
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... demasiado cerca de otra localidad
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... demasiadas localidades
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... ya no hay espacio en el mapa
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}La localidad no construirá carreteras. Se puede activar esta función en Configuración->Entorno->Localidades
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Obras de carretera en progreso
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}No se puede eliminar esta localidad...{}Aún tiene una estación o depósito, o una de sus casillas no se puede quitar
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... no hay lugar apto para una estatua en el centro de esta localidad

View File

@ -4845,7 +4845,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... för
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... för nära en annan stad
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... för många städer
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... det finns ingen plats kvar på kartan
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Staden kommer inte bygga vägar. Du kan tillåta att staden bygger vägar via Inställningar->Miljö->Städer
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Vägarbete pågår
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Kan inte ta bort den här staden...{}En station eller depå refererar till staden eller så kan inte en stadsägd ruta tas bort.
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... det finns ingen lämplig plats för en staty i stadens centrum

View File

@ -4278,7 +4278,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... ப
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... மற்றொரு நகரத்திற்கு மிகவும் அருகாமையில் உள்ளது
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... மிகவும் அதிகமான நகரங்கள்
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... படத்தில் வேறு வெற்றுஇடம் இல்லை
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}நகராட்சி சாலைகளை அமைக்காது. இந்த அமைப்பினை மாற்ற செல்க சிறப்பு அமைப்புகள் -> பொருளாதாரம் -> நகரங்கள்
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}சாலைப் பணிகள் நடந்துக் கொண்டிருக்கின்றன
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}இந்த நகரத்தினை நீக்க இயலாது ...{} ஒரு நிலையமோ அல்லது பணிமனையோ நகரத்தின் பெயரில் உள்ளது மற்றும் நகரத்திற்குச் சொந்தமான கட்டங்களை நீக்க முடியாது.
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... நகரத்தின் நடுவில் சிலையினை அமைக்க தகுந்த இடமில்லை

View File

@ -4411,7 +4411,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... ต
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... ใกล้กับเมืองอื่นมากเกินไป
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... มีเมืองมากเกินไป
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... มีพื้นที่บนแผนที่ไม่มากพอ
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}เมืองจะไม่สามารถสร้างถนนได้ในอนาคต. คุณสามารถเปิดใช้งานสร้างถนนของเมือง ใน Advanced Settings->Economy->Towns
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}กำลังอยู่ระหว่างการปรับปรุงถนน
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}ไม่สามารถทำลายเมืองได้{}สถานีหรือโรงเก็บนี้เป็นทรัพย์สินของเมืองไม่สามารถทำลายหรือเคลื่อนย้ายได้
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... ที่นี่ไม่มีสถานที่เหมาะสมในการสร้างอนุเสาวรีย์ในใจกลางเมือง

View File

@ -4839,7 +4839,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... 太
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... 太接近另一個市鎮
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... 已有太多市鎮
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... 地圖沒有足夠空間
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}市鎮不會自動興建道路。你可以在 [設定] -> [環境] -> [市鎮] 啟用市鎮自行興建道路的功能。
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}道路施工中
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}無法刪除此市鎮...{}市鎮範圍內還有車站或機廠或無法移除的區塊
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... 市中心沒有適合的空間建造雕像

View File

@ -4866,7 +4866,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... hari
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... başka bir şehire çok yakın
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... çok fazla şehir var
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... haritada boş yer yok
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Kasaba yol yapmayacak. Yol yapımını Gelişmiş Ayarlar->Ekonomi->Şehirler'den etkinleştirebilirsiniz
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Yol çalışmaları
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Bu kasaba silinemiyor...{}Bir istasyon veya garaj kasabaya atıfta bulunuyor ya da bir kasaba karesi kaldırılamıyor
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... bu şehrin merkezinde heykel için uygun bir yer yok

View File

@ -4924,7 +4924,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... на
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... надто близько до іншого міста
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... забагато міст
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... на карті немає вільного місця
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Місто не будуватиме дороги. Ви можете дозволити будівництво доріг через налаштування->Довкілля->Міста
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Дорога ремонтується
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Не можна видалити це місто...{}Станція або депо, що відносяться до міста або знаходяться на землі у власності міста, не можуть бути видалені
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... немає придатного місця для статуї в центрі цього міста

View File

@ -4866,7 +4866,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... quá
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... quá gần đô thị khác
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... quá nhiều đô thị
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... không còn khoảng trống nào trên bản đồ
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Đô thị sẽ không xây dựng đường phố. Bạn có thể bật tính năng này ở menu Thiết lập mở rộng->Môi trường->Đô thị
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Xây dựng cầu đường đang tiến hành
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Không thể xoá đo thị này...{}Có một ga, bến hoặc xưởng thuộc đô thị hoặc là 1 ô đất của đô thị không thể xoá được.
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... không có nơi nào hợp lý để dựng tượng đài ở trung tâm đô thị này

View File

@ -4443,7 +4443,6 @@ STR_ERROR_TOO_CLOSE_TO_EDGE_OF_MAP_SUB :{WHITE}... rhy
STR_ERROR_TOO_CLOSE_TO_ANOTHER_TOWN :{WHITE}... rhy agos i dref arall
STR_ERROR_TOO_MANY_TOWNS :{WHITE}... gormod o drefi
STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... nid oes mwy o le ar y map
STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}Ni fydd y dref yn adeiladu ffyrdd. Gallwch alluogi adeiladu ffyrdd yn Gosodiadau->Amgylchedd->Trefi
STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Mae gwaith yn cael ei wneud ar y ffordd
STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Methu dileu'r dref...{}Mae gorsaf neu depo sy'n cyfeirio i'r dref neu deil ym mherchnogaeth y dref na ellir ei ddileu
STR_ERROR_STATUE_NO_SUITABLE_PLACE :{WHITE}... nid oes man addas i'r cerflun yn nghanol y ddinas yma

View File

@ -306,19 +306,20 @@ public:
line << GetString(STR_LAND_AREA_INFORMATION_CARGO_ACCEPTED);
bool found = false;
for (CargoID i = 0; i < NUM_CARGO; ++i) {
if (acceptance[i] > 0) {
for (const CargoSpec *cs : _sorted_cargo_specs) {
CargoID cid = cs->Index();
if (acceptance[cid] > 0) {
/* Add a comma between each item. */
if (found) line << ", ";
found = true;
/* If the accepted value is less than 8, show it in 1/8:ths */
if (acceptance[i] < 8) {
SetDParam(0, acceptance[i]);
SetDParam(1, CargoSpec::Get(i)->name);
if (acceptance[cid] < 8) {
SetDParam(0, acceptance[cid]);
SetDParam(1, cs->name);
line << GetString(STR_LAND_AREA_INFORMATION_CARGO_EIGHTS);
} else {
line << GetString(CargoSpec::Get(i)->name);
line << GetString(cs->name);
}
}
}

View File

@ -116,14 +116,14 @@ template <class Tbase_set>
return BaseMedia<Tbase_set>::used_set != nullptr;
}
bool MusicSet::FillSetDetails(IniFile *ini, const std::string &path, const std::string &full_filename)
bool MusicSet::FillSetDetails(const IniFile &ini, const std::string &path, const std::string &full_filename)
{
bool ret = this->BaseSet<MusicSet, NUM_SONGS_AVAILABLE, false>::FillSetDetails(ini, path, full_filename);
if (ret) {
this->num_available = 0;
IniGroup *names = ini->GetGroup("names");
IniGroup *catindex = ini->GetGroup("catindex");
IniGroup *timingtrim = ini->GetGroup("timingtrim");
const IniGroup *names = ini.GetGroup("names");
const IniGroup *catindex = ini.GetGroup("catindex");
const IniGroup *timingtrim = ini.GetGroup("timingtrim");
uint tracknr = 1;
for (uint i = 0; i < lengthof(this->songinfo); i++) {
const std::string &filename = this->files[i].filename;
@ -133,7 +133,7 @@ bool MusicSet::FillSetDetails(IniFile *ini, const std::string &path, const std::
this->songinfo[i].filename = filename; // non-owned pointer
IniItem *item = catindex->GetItem(_music_file_names[i]);
const IniItem *item = catindex != nullptr ? catindex->GetItem(_music_file_names[i]) : nullptr;
if (item != nullptr && item->value.has_value() && !item->value->empty()) {
/* Song has a CAT file index, assume it's MPS MIDI format */
this->songinfo[i].filetype = MTT_MPSMIDI;
@ -158,7 +158,7 @@ bool MusicSet::FillSetDetails(IniFile *ini, const std::string &path, const std::
* the beginning, so we don't start reading e.g. root. */
while (*trimmed_filename == PATHSEPCHAR) trimmed_filename++;
item = names->GetItem(trimmed_filename);
item = names != nullptr ? names->GetItem(trimmed_filename) : nullptr;
if (item != nullptr && item->value.has_value() && !item->value->empty()) break;
}
@ -179,7 +179,7 @@ bool MusicSet::FillSetDetails(IniFile *ini, const std::string &path, const std::
this->songinfo[i].tracknr = tracknr++;
}
item = trimmed_filename != nullptr ? timingtrim->GetItem(trimmed_filename) : nullptr;
item = trimmed_filename != nullptr && timingtrim != nullptr ? timingtrim->GetItem(trimmed_filename) : nullptr;
if (item != nullptr && item->value.has_value() && !item->value->empty()) {
auto endpos = item->value->find(':');
if (endpos != std::string::npos) {

View File

@ -72,9 +72,9 @@ static DropDownList BuildVisibilityDropDownList()
{
DropDownList list;
list.emplace_back(new DropDownListStringItem(STR_NETWORK_SERVER_VISIBILITY_LOCAL, SERVER_GAME_TYPE_LOCAL, false));
list.emplace_back(new DropDownListStringItem(STR_NETWORK_SERVER_VISIBILITY_INVITE_ONLY, SERVER_GAME_TYPE_INVITE_ONLY, false));
list.emplace_back(new DropDownListStringItem(STR_NETWORK_SERVER_VISIBILITY_PUBLIC, SERVER_GAME_TYPE_PUBLIC, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_NETWORK_SERVER_VISIBILITY_LOCAL, SERVER_GAME_TYPE_LOCAL, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_NETWORK_SERVER_VISIBILITY_INVITE_ONLY, SERVER_GAME_TYPE_INVITE_ONLY, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_NETWORK_SERVER_VISIBILITY_PUBLIC, SERVER_GAME_TYPE_PUBLIC, false));
return list;
}
@ -1544,8 +1544,8 @@ private:
static void OnClickClientAdmin([[maybe_unused]] NetworkClientListWindow *w, [[maybe_unused]] Point pt, ClientID client_id)
{
DropDownList list;
list.emplace_back(new DropDownListStringItem(STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK, DD_CLIENT_ADMIN_KICK, false));
list.emplace_back(new DropDownListStringItem(STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN, DD_CLIENT_ADMIN_BAN, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_KICK, DD_CLIENT_ADMIN_KICK, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_BAN, DD_CLIENT_ADMIN_BAN, false));
Rect wi_rect;
wi_rect.left = pt.x;
@ -1566,8 +1566,8 @@ private:
static void OnClickCompanyAdmin([[maybe_unused]] NetworkClientListWindow *w, [[maybe_unused]] Point pt, CompanyID company_id)
{
DropDownList list;
list.emplace_back(new DropDownListStringItem(STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET, DD_COMPANY_ADMIN_RESET, NetworkCompanyHasClients(company_id)));
list.emplace_back(new DropDownListStringItem(STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK, DD_COMPANY_ADMIN_UNLOCK, !NetworkCompanyIsPassworded(company_id)));
list.push_back(std::make_unique<DropDownListStringItem>(STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_RESET, DD_COMPANY_ADMIN_RESET, NetworkCompanyHasClients(company_id)));
list.push_back(std::make_unique<DropDownListStringItem>(STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_UNLOCK, DD_COMPANY_ADMIN_UNLOCK, !NetworkCompanyIsPassworded(company_id)));
Rect wi_rect;
wi_rect.left = pt.x;
@ -1598,9 +1598,9 @@ private:
{
ButtonCommon *chat_button = new CompanyButton(SPR_CHAT, company_id == COMPANY_SPECTATOR ? STR_NETWORK_CLIENT_LIST_CHAT_SPECTATOR_TOOLTIP : STR_NETWORK_CLIENT_LIST_CHAT_COMPANY_TOOLTIP, COLOUR_ORANGE, company_id, &NetworkClientListWindow::OnClickCompanyChat);
if (_network_server) this->buttons[line_count].emplace_back(new CompanyButton(SPR_ADMIN, STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP, COLOUR_RED, company_id, &NetworkClientListWindow::OnClickCompanyAdmin, company_id == COMPANY_SPECTATOR));
if (_network_server) this->buttons[line_count].push_back(std::make_unique<CompanyButton>(SPR_ADMIN, STR_NETWORK_CLIENT_LIST_ADMIN_COMPANY_TOOLTIP, COLOUR_RED, company_id, &NetworkClientListWindow::OnClickCompanyAdmin, company_id == COMPANY_SPECTATOR));
this->buttons[line_count].emplace_back(chat_button);
if (client_playas != company_id) this->buttons[line_count].emplace_back(new CompanyButton(SPR_JOIN, STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP, COLOUR_ORANGE, company_id, &NetworkClientListWindow::OnClickCompanyJoin, company_id != COMPANY_SPECTATOR && Company::Get(company_id)->is_ai));
if (client_playas != company_id) this->buttons[line_count].push_back(std::make_unique<CompanyButton>(SPR_JOIN, STR_NETWORK_CLIENT_LIST_JOIN_TOOLTIP, COLOUR_ORANGE, company_id, &NetworkClientListWindow::OnClickCompanyJoin, company_id != COMPANY_SPECTATOR && Company::Get(company_id)->is_ai));
this->line_count += 1;
@ -1609,8 +1609,8 @@ private:
if (ci->client_playas != company_id) continue;
has_players = true;
if (_network_server) this->buttons[line_count].emplace_back(new ClientButton(SPR_ADMIN, STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP, COLOUR_RED, ci->client_id, &NetworkClientListWindow::OnClickClientAdmin, _network_own_client_id == ci->client_id));
if (_network_own_client_id != ci->client_id) this->buttons[line_count].emplace_back(new ClientButton(SPR_CHAT, STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP, COLOUR_ORANGE, ci->client_id, &NetworkClientListWindow::OnClickClientChat));
if (_network_server) this->buttons[line_count].push_back(std::make_unique<ClientButton>(SPR_ADMIN, STR_NETWORK_CLIENT_LIST_ADMIN_CLIENT_TOOLTIP, COLOUR_RED, ci->client_id, &NetworkClientListWindow::OnClickClientAdmin, _network_own_client_id == ci->client_id));
if (_network_own_client_id != ci->client_id) this->buttons[line_count].push_back(std::make_unique<ClientButton>(SPR_CHAT, STR_NETWORK_CLIENT_LIST_CHAT_CLIENT_TOOLTIP, COLOUR_ORANGE, ci->client_id, &NetworkClientListWindow::OnClickClientChat));
if (ci->client_id == _network_own_client_id) {
this->player_self_index = this->line_count;
@ -1640,7 +1640,7 @@ private:
/* As spectator, show a line to create a new company. */
if (client_playas == COMPANY_SPECTATOR && !NetworkMaxCompaniesReached()) {
this->buttons[line_count].emplace_back(new CompanyButton(SPR_JOIN, STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP, COLOUR_ORANGE, COMPANY_SPECTATOR, &NetworkClientListWindow::OnClickCompanyNew));
this->buttons[line_count].push_back(std::make_unique<CompanyButton>(SPR_JOIN, STR_NETWORK_CLIENT_LIST_NEW_COMPANY_TOOLTIP, COLOUR_ORANGE, COMPANY_SPECTATOR, &NetworkClientListWindow::OnClickCompanyNew));
this->line_count += 1;
}

View File

@ -8850,7 +8850,7 @@ void ResetPersistentNewGRFData()
*/
static void BuildCargoTranslationMap()
{
memset(_cur.grffile->cargo_map, 0xFF, sizeof(_cur.grffile->cargo_map));
_cur.grffile->cargo_map.fill(UINT8_MAX);
for (const CargoSpec *cs : CargoSpec::Iterate()) {
if (!cs->IsValid()) continue;
@ -9067,20 +9067,13 @@ static void CalculateRefitMasks()
* cargo type. Finally disable the vehicle, if there is still no cargo. */
if (!IsValidCargoID(ei->cargo_type) && ei->refit_mask != 0) {
/* Figure out which CTT to use for the default cargo, if it is 'first refittable'. */
const uint8_t *cargo_map_for_first_refittable = nullptr;
{
const GRFFile *file = _gted[engine].defaultcargo_grf;
if (file == nullptr) file = e->GetGRF();
if (file != nullptr && file->grf_version >= 8 && file->cargo_list.size() != 0) {
cargo_map_for_first_refittable = file->cargo_map;
}
}
if (cargo_map_for_first_refittable != nullptr) {
/* Use first refittable cargo from cargo translation table */
byte best_local_slot = 0xFF;
byte best_local_slot = UINT8_MAX;
for (CargoID cargo_type : SetCargoBitIterator(ei->refit_mask)) {
byte local_slot = cargo_map_for_first_refittable[cargo_type];
byte local_slot = file->cargo_map[cargo_type];
if (local_slot < best_local_slot) {
best_local_slot = local_slot;
ei->cargo_type = cargo_type;

View File

@ -127,7 +127,7 @@ struct GRFFile : ZeroedMemoryAllocator {
std::vector<GRFLabel> labels; ///< List of labels
std::vector<CargoLabel> cargo_list; ///< Cargo translation table (local ID -> label)
uint8_t cargo_map[NUM_CARGO]; ///< Inverse cargo translation table (CargoID -> local ID)
std::array<uint8_t, NUM_CARGO> cargo_map{}; ///< Inverse cargo translation table (CargoID -> local ID)
std::vector<RailTypeLabel> railtype_list; ///< Railtype translation table
RailType railtype_map[RAILTYPE_END];

View File

@ -435,19 +435,11 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec
case 0x42: { // Consist cargo information
if (!HasBit(v->grf_cache.cache_valid, NCVV_CONSIST_CARGO_INFORMATION)) {
const Vehicle *u;
std::array<uint8_t, NUM_CARGO> common_cargoes{};
byte cargo_classes = 0;
uint8_t common_cargoes[NUM_CARGO];
uint8_t common_subtypes[256];
byte user_def_data = 0;
CargoID common_cargo_type = CT_INVALID;
uint8_t common_subtype = 0xFF; // Return 0xFF if nothing is carried
/* Reset our arrays */
memset(common_cargoes, 0, sizeof(common_cargoes));
memset(common_subtypes, 0, sizeof(common_subtypes));
for (u = v; u != nullptr; u = u->Next()) {
for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
if (v->type == VEH_TRAIN) user_def_data |= Train::From(u)->tcache.user_def_data;
/* Skip empty engines */
@ -458,16 +450,13 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec
}
/* Pick the most common cargo type */
uint common_cargo_best_amount = 0;
for (CargoID cargo = 0; cargo < NUM_CARGO; cargo++) {
if (common_cargoes[cargo] > common_cargo_best_amount) {
common_cargo_best_amount = common_cargoes[cargo];
common_cargo_type = cargo;
}
}
auto cargo_it = std::max_element(std::begin(common_cargoes), std::end(common_cargoes));
/* Return CT_INVALID if nothing is carried */
CargoID common_cargo_type = (*cargo_it == 0) ? (CargoID)CT_INVALID : static_cast<CargoID>(std::distance(std::begin(common_cargoes), cargo_it));
/* Count subcargo types of common_cargo_type */
for (u = v; u != nullptr; u = u->Next()) {
std::array<uint8_t, UINT8_MAX + 1> common_subtypes{};
for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
/* Skip empty engines and engines not carrying common_cargo_type */
if (u->cargo_type != common_cargo_type || !u->GetEngine()->CanCarryCargo()) continue;
@ -475,13 +464,9 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec
}
/* Pick the most common subcargo type*/
uint common_subtype_best_amount = 0;
for (uint i = 0; i < lengthof(common_subtypes); i++) {
if (common_subtypes[i] > common_subtype_best_amount) {
common_subtype_best_amount = common_subtypes[i];
common_subtype = i;
}
}
auto subtype_it = std::max_element(std::begin(common_subtypes), std::end(common_subtypes));
/* Return UINT8_MAX if nothing is carried */
uint8_t common_subtype = (*subtype_it == 0) ? UINT8_MAX : static_cast<uint8_t>(std::distance(std::begin(common_subtypes), subtype_it));
/* Note: We have to store the untranslated cargotype in the cache as the cache can be read by different NewGRFs,
* which will need different translations */

View File

@ -392,7 +392,7 @@ struct NewGRFParametersWindow : public Window {
DropDownList list;
for (uint32_t i = par_info.min_value; i <= par_info.max_value; i++) {
list.emplace_back(new DropDownListStringItem(GetGRFStringFromGRFText(par_info.value_names.find(i)->second), i, false));
list.push_back(std::make_unique<DropDownListStringItem>(GetGRFStringFromGRFText(par_info.value_names.find(i)->second), i, false));
}
ShowDropDownListAt(this, std::move(list), old_val, WID_NP_SETTING_DROPDOWN, wi_rect, COLOUR_ORANGE);
@ -952,10 +952,10 @@ struct NewGRFWindow : public Window, NewGRFScanCallback {
DropDownList list;
/* Add 'None' option for clearing list */
list.emplace_back(new DropDownListStringItem(STR_NONE, -1, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_NONE, -1, false));
for (uint i = 0; i < this->grf_presets.size(); i++) {
list.emplace_back(new DropDownListStringItem(this->grf_presets[i], i, false));
list.push_back(std::make_unique<DropDownListStringItem>(this->grf_presets[i], i, false));
}
this->CloseChildWindows(WC_QUERY_STRING); // Remove the parameter query window

View File

@ -1299,7 +1299,7 @@ public:
case WID_O_COND_VARIABLE: {
DropDownList list;
for (uint i = 0; i < lengthof(_order_conditional_variable); i++) {
list.emplace_back(new DropDownListStringItem(STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + _order_conditional_variable[i], _order_conditional_variable[i], false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_ORDER_CONDITIONAL_LOAD_PERCENTAGE + _order_conditional_variable[i], _order_conditional_variable[i], false));
}
ShowDropDownList(this, std::move(list), this->vehicle->GetOrder(this->OrderGetSel())->GetConditionVariable(), WID_O_COND_VARIABLE);
break;

View File

@ -2353,7 +2353,7 @@ DropDownList GetRailTypeDropDownList(bool for_replacement, bool all_option)
DropDownList list;
if (all_option) {
list.emplace_back(new DropDownListStringItem(STR_REPLACE_ALL_RAILTYPE, INVALID_RAILTYPE, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_REPLACE_ALL_RAILTYPE, INVALID_RAILTYPE, false));
}
Dimension d = { 0, 0 };
@ -2375,18 +2375,18 @@ DropDownList GetRailTypeDropDownList(bool for_replacement, bool all_option)
SetDParam(0, rti->strings.menu_text);
SetDParam(1, rti->max_speed);
if (for_replacement) {
list.emplace_back(new DropDownListStringItem(rti->strings.replace_text, rt, !HasBit(avail_railtypes, rt)));
list.push_back(std::make_unique<DropDownListStringItem>(rti->strings.replace_text, rt, !HasBit(avail_railtypes, rt)));
} else {
StringID str = rti->max_speed > 0 ? STR_TOOLBAR_RAILTYPE_VELOCITY : STR_JUST_STRING;
DropDownListIconItem *iconitem = new DropDownListIconItem(rti->gui_sprites.build_x_rail, PAL_NONE, str, rt, !HasBit(avail_railtypes, rt));
auto iconitem = std::make_unique<DropDownListIconItem>(rti->gui_sprites.build_x_rail, PAL_NONE, str, rt, !HasBit(avail_railtypes, rt));
iconitem->SetDimension(d);
list.emplace_back(iconitem);
list.push_back(std::move(iconitem));
}
}
if (list.size() == 0) {
/* Empty dropdowns are not allowed */
list.emplace_back(new DropDownListStringItem(STR_NONE, INVALID_RAILTYPE, true));
list.push_back(std::make_unique<DropDownListStringItem>(STR_NONE, INVALID_RAILTYPE, true));
}
return list;

View File

@ -1814,7 +1814,7 @@ DropDownList GetRoadTypeDropDownList(RoadTramTypes rtts, bool for_replacement, b
DropDownList list;
if (all_option) {
list.emplace_back(new DropDownListStringItem(STR_REPLACE_ALL_ROADTYPE, INVALID_ROADTYPE, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_REPLACE_ALL_ROADTYPE, INVALID_ROADTYPE, false));
}
Dimension d = { 0, 0 };
@ -1836,18 +1836,18 @@ DropDownList GetRoadTypeDropDownList(RoadTramTypes rtts, bool for_replacement, b
SetDParam(0, rti->strings.menu_text);
SetDParam(1, rti->max_speed / 2);
if (for_replacement) {
list.emplace_back(new DropDownListStringItem(rti->strings.replace_text, rt, !HasBit(avail_roadtypes, rt)));
list.push_back(std::make_unique<DropDownListStringItem>(rti->strings.replace_text, rt, !HasBit(avail_roadtypes, rt)));
} else {
StringID str = rti->max_speed > 0 ? STR_TOOLBAR_RAILTYPE_VELOCITY : STR_JUST_STRING;
DropDownListIconItem *iconitem = new DropDownListIconItem(rti->gui_sprites.build_x_road, PAL_NONE, str, rt, !HasBit(avail_roadtypes, rt));
auto iconitem = std::make_unique<DropDownListIconItem>(rti->gui_sprites.build_x_road, PAL_NONE, str, rt, !HasBit(avail_roadtypes, rt));
iconitem->SetDimension(d);
list.emplace_back(iconitem);
list.push_back(std::move(iconitem));
}
}
if (list.size() == 0) {
/* Empty dropdowns are not allowed */
list.emplace_back(new DropDownListStringItem(STR_NONE, INVALID_ROADTYPE, true));
list.push_back(std::make_unique<DropDownListStringItem>(STR_NONE, INVALID_ROADTYPE, true));
}
return list;
@ -1880,14 +1880,14 @@ DropDownList GetScenRoadTypeDropDownList(RoadTramTypes rtts)
SetDParam(0, rti->strings.menu_text);
SetDParam(1, rti->max_speed / 2);
StringID str = rti->max_speed > 0 ? STR_TOOLBAR_RAILTYPE_VELOCITY : STR_JUST_STRING;
DropDownListIconItem *item = new DropDownListIconItem(rti->gui_sprites.build_x_road, PAL_NONE, str, rt, !HasBit(avail_roadtypes, rt));
auto item = std::make_unique<DropDownListIconItem>(rti->gui_sprites.build_x_road, PAL_NONE, str, rt, !HasBit(avail_roadtypes, rt));
item->SetDimension(d);
list.emplace_back(item);
list.push_back(std::move(item));
}
if (list.size() == 0) {
/* Empty dropdowns are not allowed */
list.emplace_back(new DropDownListStringItem(STR_NONE, -1, true));
list.push_back(std::make_unique<DropDownListStringItem>(STR_NONE, -1, true));
}
return list;

View File

@ -40,9 +40,7 @@ void DrawRoadVehDetails(const Vehicle *v, const Rect &r)
if (v->HasArticulatedPart()) {
CargoArray max_cargo{};
StringID subtype_text[NUM_CARGO];
memset(subtype_text, 0, sizeof(subtype_text));
std::array<StringID, NUM_CARGO> subtype_text{};
for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
max_cargo[u->cargo_type] += u->cargo_cap;
@ -55,16 +53,17 @@ void DrawRoadVehDetails(const Vehicle *v, const Rect &r)
std::string capacity = GetString(STR_VEHICLE_DETAILS_TRAIN_ARTICULATED_RV_CAPACITY);
bool first = true;
for (CargoID i = 0; i < NUM_CARGO; i++) {
if (max_cargo[i] > 0) {
for (const CargoSpec *cs : _sorted_cargo_specs) {
CargoID cid = cs->Index();
if (max_cargo[cid] > 0) {
if (!first) capacity += ", ";
SetDParam(0, i);
SetDParam(1, max_cargo[i]);
SetDParam(0, cid);
SetDParam(1, max_cargo[cid]);
capacity += GetString(STR_JUST_CARGO);
if (subtype_text[i] != 0) {
capacity += GetString(subtype_text[i]);
if (subtype_text[cid] != STR_NULL) {
capacity += GetString(subtype_text[cid]);
}
first = false;

View File

@ -469,7 +469,7 @@ struct ScriptSettingsWindow : public Window {
DropDownList list;
for (int i = config_item.min_value; i <= config_item.max_value; i++) {
list.emplace_back(new DropDownListStringItem(config_item.labels.find(i)->second, i, false));
list.push_back(std::make_unique<DropDownListStringItem>(config_item.labels.find(i)->second, i, false));
}
ShowDropDownListAt(this, std::move(list), old_val, WID_SCRS_SETTING_DROPDOWN, wi_rect, COLOUR_ORANGE);

View File

@ -131,12 +131,11 @@ static bool IsSignedVarMemType(VarType vt)
*/
class ConfigIniFile : public IniFile {
private:
inline static const char * const list_group_names[] = {
inline static const IniGroupNameList list_group_names = {
"bans",
"newgrf",
"servers",
"server_bind_addresses",
nullptr,
};
public:
@ -587,8 +586,8 @@ const std::string &StringSettingDesc::Read(const void *object) const
*/
static void IniLoadSettings(IniFile &ini, const SettingTable &settings_table, const char *grpname, void *object, bool only_startup)
{
IniGroup *group;
IniGroup *group_def = ini.GetGroup(grpname);
const IniGroup *group;
const IniGroup *group_def = ini.GetGroup(grpname);
for (auto &desc : settings_table) {
const SettingDesc *sd = GetSettingDesc(desc);
@ -600,13 +599,15 @@ static void IniLoadSettings(IniFile &ini, const SettingTable &settings_table, co
auto sc = s.find('.');
if (sc != std::string::npos) {
group = ini.GetGroup(s.substr(0, sc));
if (group == nullptr) group = group_def;
s = s.substr(sc + 1);
} else {
group = group_def;
}
IniItem *item = group->GetItem(s);
if (item == nullptr && group != group_def) {
const IniItem *item = nullptr;
if (group != nullptr) item = group->GetItem(s);
if (item == nullptr && group != group_def && group_def != nullptr) {
/* For settings.xx.yy load the settings from [settings] yy = ? in case the previous
* did not exist (e.g. loading old config files with a [settings] section */
item = group_def->GetItem(s);
@ -615,7 +616,9 @@ static void IniLoadSettings(IniFile &ini, const SettingTable &settings_table, co
/* For settings.xx.zz.yy load the settings from [zz] yy = ? in case the previous
* did not exist (e.g. loading old config files with a [yapf] section */
sc = s.find('.');
if (sc != std::string::npos) item = ini.GetGroup(s.substr(0, sc))->GetItem(s.substr(sc + 1));
if (sc != std::string::npos) {
if (group = ini.GetGroup(s.substr(0, sc)); group != nullptr) item = group->GetItem(s.substr(sc + 1));
}
}
sd->ParseValue(item, object);
@ -676,10 +679,10 @@ static void IniSaveSettings(IniFile &ini, const SettingTable &settings_table, co
std::string s{ sd->GetName() };
auto sc = s.find('.');
if (sc != std::string::npos) {
group = ini.GetGroup(s.substr(0, sc));
group = &ini.GetOrCreateGroup(s.substr(0, sc));
s = s.substr(sc + 1);
} else {
if (group_def == nullptr) group_def = ini.GetGroup(grpname);
if (group_def == nullptr) group_def = &ini.GetOrCreateGroup(grpname);
group = group_def;
}
@ -777,14 +780,14 @@ bool ListSettingDesc::IsDefaultValue(void *) const
*/
static void IniLoadSettingList(IniFile &ini, const char *grpname, StringList &list)
{
IniGroup *group = ini.GetGroup(grpname);
const IniGroup *group = ini.GetGroup(grpname);
if (group == nullptr) return;
list.clear();
for (const IniItem *item = group->item; item != nullptr; item = item->next) {
if (!item->name.empty()) list.push_back(item->name);
for (const IniItem &item : group->items) {
if (!item.name.empty()) list.push_back(item.name);
}
}
@ -799,13 +802,11 @@ static void IniLoadSettingList(IniFile &ini, const char *grpname, StringList &li
*/
static void IniSaveSettingList(IniFile &ini, const char *grpname, StringList &list)
{
IniGroup *group = ini.GetGroup(grpname);
if (group == nullptr) return;
group->Clear();
IniGroup &group = ini.GetOrCreateGroup(grpname);
group.Clear();
for (const auto &iter : list) {
group->GetOrCreateItem(iter).SetValue("");
group.GetOrCreateItem(iter).SetValue("");
}
}
@ -893,10 +894,9 @@ static void ValidateSettings()
}
}
static void AILoadConfig(IniFile &ini, const char *grpname)
static void AILoadConfig(const IniFile &ini, const char *grpname)
{
IniGroup *group = ini.GetGroup(grpname);
IniItem *item;
const IniGroup *group = ini.GetGroup(grpname);
/* Clean any configured AI */
for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
@ -907,44 +907,44 @@ static void AILoadConfig(IniFile &ini, const char *grpname)
if (group == nullptr) return;
CompanyID c = COMPANY_FIRST;
for (item = group->item; c < MAX_COMPANIES && item != nullptr; c++, item = item->next) {
for (const IniItem &item : group->items) {
AIConfig *config = AIConfig::GetConfig(c, AIConfig::SSS_FORCE_NEWGAME);
config->Change(item->name);
config->Change(item.name);
if (!config->HasScript()) {
if (item->name != "none") {
Debug(script, 0, "The AI by the name '{}' was no longer found, and removed from the list.", item->name);
if (item.name != "none") {
Debug(script, 0, "The AI by the name '{}' was no longer found, and removed from the list.", item.name);
continue;
}
}
if (item->value.has_value()) config->StringToSettings(*item->value);
if (item.value.has_value()) config->StringToSettings(*item.value);
c++;
if (c >= MAX_COMPANIES) break;
}
}
static void GameLoadConfig(IniFile &ini, const char *grpname)
static void GameLoadConfig(const IniFile &ini, const char *grpname)
{
IniGroup *group = ini.GetGroup(grpname);
IniItem *item;
const IniGroup *group = ini.GetGroup(grpname);
/* Clean any configured GameScript */
GameConfig::GetConfig(GameConfig::SSS_FORCE_NEWGAME)->Change(std::nullopt);
/* If no group exists, return */
if (group == nullptr) return;
if (group == nullptr || group->items.empty()) return;
item = group->item;
if (item == nullptr) return;
const IniItem &item = group->items.front();
GameConfig *config = GameConfig::GetConfig(AIConfig::SSS_FORCE_NEWGAME);
config->Change(item->name);
config->Change(item.name);
if (!config->HasScript()) {
if (item->name != "none") {
Debug(script, 0, "The GameScript by the name '{}' was no longer found, and removed from the list.", item->name);
if (item.name != "none") {
Debug(script, 0, "The GameScript by the name '{}' was no longer found, and removed from the list.", item.name);
return;
}
}
if (item->value.has_value()) config->StringToSettings(*item->value);
if (item.value.has_value()) config->StringToSettings(*item.value);
}
/**
@ -987,22 +987,21 @@ static bool DecodeHexText(const char *pos, uint8_t *dest, size_t dest_size)
* @param grpname Group name containing the configuration of the GRF.
* @param is_static GRF is static.
*/
static GRFConfig *GRFLoadConfig(IniFile &ini, const char *grpname, bool is_static)
static GRFConfig *GRFLoadConfig(const IniFile &ini, const char *grpname, bool is_static)
{
IniGroup *group = ini.GetGroup(grpname);
IniItem *item;
const IniGroup *group = ini.GetGroup(grpname);
GRFConfig *first = nullptr;
GRFConfig **curr = &first;
if (group == nullptr) return nullptr;
uint num_grfs = 0;
for (item = group->item; item != nullptr; item = item->next) {
for (const IniItem &item : group->items) {
GRFConfig *c = nullptr;
uint8_t grfid_buf[4];
MD5Hash md5sum;
const char *filename = item->name.c_str();
const char *filename = item.name.c_str();
bool has_grfid = false;
bool has_md5sum = false;
@ -1026,8 +1025,8 @@ static GRFConfig *GRFLoadConfig(IniFile &ini, const char *grpname, bool is_stati
if (c == nullptr) c = new GRFConfig(filename);
/* Parse parameters */
if (item->value.has_value() && !item->value->empty()) {
int count = ParseIntList(item->value->c_str(), c->param.data(), c->param.size());
if (item.value.has_value() && !item.value->empty()) {
int count = ParseIntList(item.value->c_str(), c->param.data(), c->param.size());
if (count < 0) {
SetDParamStr(0, filename);
ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_ARRAY, WL_CRITICAL);
@ -1050,7 +1049,7 @@ static GRFConfig *GRFLoadConfig(IniFile &ini, const char *grpname, bool is_stati
SetDParam(1, STR_CONFIG_ERROR_INVALID_GRF_UNKNOWN);
}
SetDParamStr(0, StrEmpty(filename) ? item->name.c_str() : filename);
SetDParamStr(0, StrEmpty(filename) ? item.name.c_str() : filename);
ShowErrorMessage(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_GRF, WL_CRITICAL);
delete c;
continue;
@ -1089,9 +1088,10 @@ static GRFConfig *GRFLoadConfig(IniFile &ini, const char *grpname, bool is_stati
return first;
}
static IniFileVersion LoadVersionFromConfig(IniFile &ini)
static IniFileVersion LoadVersionFromConfig(const IniFile &ini)
{
IniGroup *group = ini.GetGroup("version");
const IniGroup *group = ini.GetGroup("version");
if (group == nullptr) return IFV_0;
auto version_number = group->GetItem("ini_version");
/* Older ini-file versions don't have this key yet. */
@ -1105,10 +1105,8 @@ static IniFileVersion LoadVersionFromConfig(IniFile &ini)
static void AISaveConfig(IniFile &ini, const char *grpname)
{
IniGroup *group = ini.GetGroup(grpname);
if (group == nullptr) return;
group->Clear();
IniGroup &group = ini.GetOrCreateGroup(grpname);
group.Clear();
for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
AIConfig *config = AIConfig::GetConfig(c, AIConfig::SSS_FORCE_NEWGAME);
@ -1121,17 +1119,14 @@ static void AISaveConfig(IniFile &ini, const char *grpname)
name = "none";
}
IniItem *item = new IniItem(group, name);
item->SetValue(value);
group.CreateItem(name).SetValue(value);
}
}
static void GameSaveConfig(IniFile &ini, const char *grpname)
{
IniGroup *group = ini.GetGroup(grpname);
if (group == nullptr) return;
group->Clear();
IniGroup &group = ini.GetOrCreateGroup(grpname);
group.Clear();
GameConfig *config = GameConfig::GetConfig(AIConfig::SSS_FORCE_NEWGAME);
std::string name;
@ -1143,8 +1138,7 @@ static void GameSaveConfig(IniFile &ini, const char *grpname)
name = "none";
}
IniItem *item = new IniItem(group, name);
item->SetValue(value);
group.CreateItem(name).SetValue(value);
}
/**
@ -1153,23 +1147,23 @@ static void GameSaveConfig(IniFile &ini, const char *grpname)
*/
static void SaveVersionInConfig(IniFile &ini)
{
IniGroup *group = ini.GetGroup("version");
group->GetOrCreateItem("version_string").SetValue(_openttd_revision);
group->GetOrCreateItem("version_number").SetValue(fmt::format("{:08X}", _openttd_newgrf_version));
group->GetOrCreateItem("ini_version").SetValue(std::to_string(INIFILE_VERSION));
IniGroup &group = ini.GetOrCreateGroup("version");
group.GetOrCreateItem("version_string").SetValue(_openttd_revision);
group.GetOrCreateItem("version_number").SetValue(fmt::format("{:08X}", _openttd_newgrf_version));
group.GetOrCreateItem("ini_version").SetValue(std::to_string(INIFILE_VERSION));
}
/* Save a GRF configuration to the given group name */
static void GRFSaveConfig(IniFile &ini, const char *grpname, const GRFConfig *list)
{
ini.RemoveGroup(grpname);
IniGroup *group = ini.GetGroup(grpname);
IniGroup &group = ini.GetOrCreateGroup(grpname);
group.Clear();
const GRFConfig *c;
for (c = list; c != nullptr; c = c->next) {
std::string key = fmt::format("{:08X}|{}|{}", BSWAP32(c->ident.grfid),
FormatArrayAsHex(c->ident.md5sum), c->filename);
group->GetOrCreateItem(key).SetValue(GRFBuildParamList(c));
group.GetOrCreateItem(key).SetValue(GRFBuildParamList(c));
}
}
@ -1223,6 +1217,7 @@ static void RemoveEntriesFromIni(IniFile &ini, const SettingTable &table)
if (sc == std::string::npos) continue;
IniGroup *group = ini.GetGroup(s.substr(0, sc));
if (group == nullptr) continue;
s = s.substr(sc + 1);
group->RemoveItem(s);
@ -1252,16 +1247,16 @@ static void RemoveEntriesFromIni(IniFile &ini, const SettingTable &table)
* @param[out] old_item The old item to base upgrading on.
* @return Whether upgrading should happen; if false, old_item is a nullptr.
*/
bool IsConversionNeeded(ConfigIniFile &ini, std::string group, std::string old_var, std::string new_var, IniItem **old_item)
bool IsConversionNeeded(const ConfigIniFile &ini, const std::string &group, const std::string &old_var, const std::string &new_var, const IniItem **old_item)
{
*old_item = nullptr;
IniGroup *igroup = ini.GetGroup(group, false);
const IniGroup *igroup = ini.GetGroup(group);
/* If the group doesn't exist, there is nothing to convert. */
if (igroup == nullptr) return false;
IniItem *tmp_old_item = igroup->GetItem(old_var);
IniItem *new_item = igroup->GetItem(new_var);
const IniItem *tmp_old_item = igroup->GetItem(old_var);
const IniItem *new_item = igroup->GetItem(new_var);
/* If the old item doesn't exist, there is nothing to convert. */
if (tmp_old_item == nullptr) return false;
@ -1306,9 +1301,9 @@ void LoadFromConfig(bool startup)
/* Move no_http_content_downloads and use_relay_service from generic_ini to private_ini. */
if (generic_version < IFV_NETWORK_PRIVATE_SETTINGS) {
IniGroup *network = generic_ini.GetGroup("network", false);
const IniGroup *network = generic_ini.GetGroup("network");
if (network != nullptr) {
IniItem *no_http_content_downloads = network->GetItem("no_http_content_downloads");
const IniItem *no_http_content_downloads = network->GetItem("no_http_content_downloads");
if (no_http_content_downloads != nullptr) {
if (no_http_content_downloads->value == "true") {
_settings_client.network.no_http_content_downloads = true;
@ -1317,7 +1312,7 @@ void LoadFromConfig(bool startup)
}
}
IniItem *use_relay_service = network->GetItem("use_relay_service");
const IniItem *use_relay_service = network->GetItem("use_relay_service");
if (use_relay_service != nullptr) {
if (use_relay_service->value == "never") {
_settings_client.network.use_relay_service = UseRelayService::URS_NEVER;
@ -1330,7 +1325,7 @@ void LoadFromConfig(bool startup)
}
}
IniItem *old_item;
const IniItem *old_item;
if (generic_version < IFV_GAME_TYPE && IsConversionNeeded(generic_ini, "network", "server_advertise", "server_game_type", &old_item)) {
auto old_value = BoolSettingDesc::ParseSingleValue(old_item->value->c_str());
@ -1388,8 +1383,8 @@ void SaveToConfig()
* just so we can add a comment before it (that is how IniFile works).
* This to explain what the file is about. After doing it once, never touch
* it again, as otherwise we might be reverting user changes. */
if (!private_ini.GetGroup("private", false)) private_ini.GetGroup("private")->comment = "; This file possibly contains private information which can identify you as person.\n";
if (!secrets_ini.GetGroup("secrets", false)) secrets_ini.GetGroup("secrets")->comment = "; Do not share this file with others, not even if they claim to be technical support.\n; This file contains saved passwords and other secrets that should remain private to you!\n";
if (IniGroup *group = private_ini.GetGroup("private"); group != nullptr) group->comment = "; This file possibly contains private information which can identify you as person.\n";
if (IniGroup *group = secrets_ini.GetGroup("secrets"); group != nullptr) group->comment = "; Do not share this file with others, not even if they claim to be technical support.\n; This file contains saved passwords and other secrets that should remain private to you!\n";
if (generic_version == IFV_0) {
/* Remove some obsolete groups. These have all been loaded into other groups. */
@ -1413,7 +1408,7 @@ void SaveToConfig()
/* These variables are migrated from generic ini to private ini now. */
if (generic_version < IFV_NETWORK_PRIVATE_SETTINGS) {
IniGroup *network = generic_ini.GetGroup("network", false);
IniGroup *network = generic_ini.GetGroup("network");
if (network != nullptr) {
network->RemoveItem("no_http_content_downloads");
network->RemoveItem("use_relay_service");
@ -1444,9 +1439,9 @@ StringList GetGRFPresetList()
StringList list;
ConfigIniFile ini(_config_file);
for (IniGroup *group = ini.group; group != nullptr; group = group->next) {
if (group->name.compare(0, 7, "preset-") == 0) {
list.push_back(group->name.substr(7));
for (const IniGroup &group : ini.groups) {
if (group.name.compare(0, 7, "preset-") == 0) {
list.push_back(group.name.substr(7));
}
}

View File

@ -213,18 +213,18 @@ struct GameOptionsWindow : Window {
int i = &currency - _currency_specs;
if (i == CURRENCY_CUSTOM) continue;
if (currency.code.empty()) {
list.emplace_back(new DropDownListStringItem(currency.name, i, HasBit(disabled, i)));
list.push_back(std::make_unique<DropDownListStringItem>(currency.name, i, HasBit(disabled, i)));
} else {
SetDParam(0, currency.name);
SetDParamStr(1, currency.code);
list.emplace_back(new DropDownListStringItem(STR_GAME_OPTIONS_CURRENCY_CODE, i, HasBit(disabled, i)));
list.push_back(std::make_unique<DropDownListStringItem>(STR_GAME_OPTIONS_CURRENCY_CODE, i, HasBit(disabled, i)));
}
}
std::sort(list.begin(), list.end(), DropDownListStringItem::NatSortFunc);
/* Append custom currency at the end */
list.emplace_back(new DropDownListItem(-1, false)); // separator line
list.emplace_back(new DropDownListStringItem(STR_GAME_OPTIONS_CURRENCY_CUSTOM, CURRENCY_CUSTOM, HasBit(disabled, CURRENCY_CUSTOM)));
list.push_back(std::make_unique<DropDownListItem>(-1, false)); // separator line
list.push_back(std::make_unique<DropDownListStringItem>(STR_GAME_OPTIONS_CURRENCY_CUSTOM, CURRENCY_CUSTOM, HasBit(disabled, CURRENCY_CUSTOM)));
break;
}
@ -238,7 +238,7 @@ struct GameOptionsWindow : Window {
const StringID *items = _autosave_dropdown;
for (uint i = 0; *items != INVALID_STRING_ID; items++, i++) {
list.emplace_back(new DropDownListStringItem(*items, i, false));
list.push_back(std::make_unique<DropDownListStringItem>(*items, i, false));
}
break;
}
@ -260,7 +260,7 @@ struct GameOptionsWindow : Window {
SetDParamStr(0, _languages[i].name);
}
SetDParam(1, (LANGUAGE_TOTAL_STRINGS - _languages[i].missing) * 100 / LANGUAGE_TOTAL_STRINGS);
list.emplace_back(new DropDownListStringItem(hide_percentage ? STR_JUST_RAW_STRING : STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE, i, false));
list.push_back(std::make_unique<DropDownListStringItem>(hide_percentage ? STR_JUST_RAW_STRING : STR_GAME_OPTIONS_LANGUAGE_PERCENTAGE, i, false));
}
std::sort(list.begin(), list.end(), DropDownListStringItem::NatSortFunc);
break;
@ -273,7 +273,7 @@ struct GameOptionsWindow : Window {
for (uint i = 0; i < _resolutions.size(); i++) {
SetDParam(0, _resolutions[i].width);
SetDParam(1, _resolutions[i].height);
list.emplace_back(new DropDownListStringItem(STR_GAME_OPTIONS_RESOLUTION_ITEM, i, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_GAME_OPTIONS_RESOLUTION_ITEM, i, false));
}
break;
@ -282,7 +282,7 @@ struct GameOptionsWindow : Window {
auto i = std::distance(_refresh_rates.begin(), it);
if (*it == _settings_client.gui.refresh_rate) *selected_index = i;
SetDParam(0, *it);
list.emplace_back(new DropDownListStringItem(STR_GAME_OPTIONS_REFRESH_RATE_ITEM, i, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_GAME_OPTIONS_REFRESH_RATE_ITEM, i, false));
}
break;
@ -2219,15 +2219,15 @@ struct GameSettingsWindow : Window {
* we don't want to allow comparing with new game's settings. */
bool disabled = mode == RM_CHANGED_AGAINST_NEW && settings_ptr == &_settings_newgame;
list.emplace_back(new DropDownListStringItem(_game_settings_restrict_dropdown[mode], mode, disabled));
list.push_back(std::make_unique<DropDownListStringItem>(_game_settings_restrict_dropdown[mode], mode, disabled));
}
break;
case WID_GS_TYPE_DROPDOWN:
list.emplace_back(new DropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL, ST_ALL, false));
list.emplace_back(new DropDownListStringItem(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME, ST_GAME, false));
list.emplace_back(new DropDownListStringItem(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME, ST_COMPANY, false));
list.emplace_back(new DropDownListStringItem(STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT, ST_CLIENT, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_CONFIG_SETTING_TYPE_DROPDOWN_ALL, ST_ALL, false));
list.push_back(std::make_unique<DropDownListStringItem>(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_GAME_INGAME, ST_GAME, false));
list.push_back(std::make_unique<DropDownListStringItem>(_game_mode == GM_MENU ? STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_MENU : STR_CONFIG_SETTING_TYPE_DROPDOWN_COMPANY_INGAME, ST_COMPANY, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_CONFIG_SETTING_TYPE_DROPDOWN_CLIENT, ST_CLIENT, false));
break;
}
return list;
@ -2391,7 +2391,7 @@ struct GameSettingsWindow : Window {
DropDownList list;
for (int i = sd->min; i <= (int)sd->max; i++) {
list.emplace_back(new DropDownListStringItem(sd->str_val + i - sd->min, i, false));
list.push_back(std::make_unique<DropDownListStringItem>(sd->str_val + i - sd->min, i, false));
}
ShowDropDownListAt(this, std::move(list), value, WID_GS_SETTING_DROPDOWN, wi_rect, COLOUR_ORANGE);

View File

@ -29,7 +29,7 @@ DropDownList BuildSetDropDownList(int *selected_index)
*selected_index = T::GetIndexOfUsedSet();
DropDownList list;
for (int i = 0; i < n; i++) {
list.emplace_back(new DropDownListStringItem(T::GetSet(i)->name, i, false));
list.push_back(std::make_unique<DropDownListStringItem>(T::GetSet(i)->name, i, false));
}
return list;
}

View File

@ -151,10 +151,10 @@ private:
struct SettingsIniFile : IniLoadFile {
/**
* Construct a new ini loader.
* @param list_group_names A \c nullptr terminated list with group names that should be loaded as lists instead of variables. @see IGT_LIST
* @param seq_group_names A \c nullptr terminated list with group names that should be loaded as lists of names. @see IGT_SEQUENCE
* @param list_group_names A list with group names that should be loaded as lists instead of variables. @see IGT_LIST
* @param seq_group_names A list with group names that should be loaded as lists of names. @see IGT_SEQUENCE
*/
SettingsIniFile(const char * const *list_group_names = nullptr, const char * const *seq_group_names = nullptr) :
SettingsIniFile(const IniGroupNameList &list_group_names = {}, const IniGroupNameList &seq_group_names = {}) :
IniLoadFile(list_group_names, seq_group_names)
{
}
@ -188,32 +188,18 @@ static const char *TEMPLATES_GROUP_NAME = "templates"; ///< Name of the group co
static const char *VALIDATION_GROUP_NAME = "validation"; ///< Name of the group containing the validation statements.
static const char *DEFAULTS_GROUP_NAME = "defaults"; ///< Name of the group containing default values for the template variables.
/**
* Load the INI file.
* @param filename Name of the file to load.
* @return Loaded INI data.
*/
static IniLoadFile *LoadIniFile(const char *filename)
{
static const char * const seq_groups[] = {PREAMBLE_GROUP_NAME, POSTAMBLE_GROUP_NAME, nullptr};
IniLoadFile *ini = new SettingsIniFile(nullptr, seq_groups);
ini->LoadFromDisk(filename, NO_DIRECTORY);
return ini;
}
/**
* Dump a #IGT_SEQUENCE group into #_stored_output.
* @param ifile Loaded INI data.
* @param group_name Name of the group to copy.
*/
static void DumpGroup(IniLoadFile *ifile, const char * const group_name)
static void DumpGroup(const IniLoadFile &ifile, const char * const group_name)
{
IniGroup *grp = ifile->GetGroup(group_name, false);
const IniGroup *grp = ifile.GetGroup(group_name);
if (grp != nullptr && grp->type == IGT_SEQUENCE) {
for (IniItem *item = grp->item; item != nullptr; item = item->next) {
if (!item->name.empty()) {
_stored_output.Add(item->name.c_str());
for (const IniItem &item : grp->items) {
if (!item.name.empty()) {
_stored_output.Add(item.name.c_str());
_stored_output.Add("\n", 1);
}
}
@ -227,9 +213,9 @@ static void DumpGroup(IniLoadFile *ifile, const char * const group_name)
* @param defaults Fallback group to search, \c nullptr skips the search.
* @return Text of the item if found, else \c nullptr.
*/
static const char *FindItemValue(const char *name, IniGroup *grp, IniGroup *defaults)
static const char *FindItemValue(const char *name, const IniGroup *grp, const IniGroup *defaults)
{
IniItem *item = grp->GetItem(name);
const IniItem *item = grp->GetItem(name);
if (item == nullptr && defaults != nullptr) item = defaults->GetItem(name);
if (item == nullptr || !item->value.has_value()) return nullptr;
return item->value->c_str();
@ -242,18 +228,18 @@ static const char *FindItemValue(const char *name, IniGroup *grp, IniGroup *defa
* @param default_grp Default values for items not set in @grp.
* @param output Output to use for result.
*/
static void DumpLine(IniItem *item, IniGroup *grp, IniGroup *default_grp, OutputStore &output)
static void DumpLine(const IniItem *item, const IniGroup *grp, const IniGroup *default_grp, OutputStore &output)
{
static const int MAX_VAR_LENGTH = 64;
/* Prefix with #if/#ifdef/#ifndef */
static const char * const pp_lines[] = {"if", "ifdef", "ifndef", nullptr};
static const auto pp_lines = {"if", "ifdef", "ifndef"};
int count = 0;
for (const char * const *name = pp_lines; *name != nullptr; name++) {
const char *condition = FindItemValue(*name, grp, default_grp);
for (const auto &name : pp_lines) {
const char *condition = FindItemValue(name, grp, default_grp);
if (condition != nullptr) {
output.Add("#", 1);
output.Add(*name);
output.Add(name);
output.Add(" ", 1);
output.Add(condition);
output.Add("\n", 1);
@ -306,31 +292,30 @@ static void DumpLine(IniItem *item, IniGroup *grp, IniGroup *default_grp, Output
* Output all non-special sections through the template / template variable expansion system.
* @param ifile Loaded INI data.
*/
static void DumpSections(IniLoadFile *ifile)
static void DumpSections(const IniLoadFile &ifile)
{
static const char * const special_group_names[] = {PREAMBLE_GROUP_NAME, POSTAMBLE_GROUP_NAME, DEFAULTS_GROUP_NAME, TEMPLATES_GROUP_NAME, VALIDATION_GROUP_NAME, nullptr};
static const auto special_group_names = {PREAMBLE_GROUP_NAME, POSTAMBLE_GROUP_NAME, DEFAULTS_GROUP_NAME, TEMPLATES_GROUP_NAME, VALIDATION_GROUP_NAME};
IniGroup *default_grp = ifile->GetGroup(DEFAULTS_GROUP_NAME, false);
IniGroup *templates_grp = ifile->GetGroup(TEMPLATES_GROUP_NAME, false);
IniGroup *validation_grp = ifile->GetGroup(VALIDATION_GROUP_NAME, false);
const IniGroup *default_grp = ifile.GetGroup(DEFAULTS_GROUP_NAME);
const IniGroup *templates_grp = ifile.GetGroup(TEMPLATES_GROUP_NAME);
const IniGroup *validation_grp = ifile.GetGroup(VALIDATION_GROUP_NAME);
if (templates_grp == nullptr) return;
/* Output every group, using its name as template name. */
for (IniGroup *grp = ifile->group; grp != nullptr; grp = grp->next) {
const char * const *sgn;
for (sgn = special_group_names; *sgn != nullptr; sgn++) if (grp->name == *sgn) break;
if (*sgn != nullptr) continue;
for (const IniGroup &grp : ifile.groups) {
/* Exclude special group names. */
if (std::find(std::begin(special_group_names), std::end(special_group_names), grp.name) != std::end(special_group_names)) continue;
IniItem *template_item = templates_grp->GetItem(grp->name); // Find template value.
const IniItem *template_item = templates_grp->GetItem(grp.name); // Find template value.
if (template_item == nullptr || !template_item->value.has_value()) {
FatalError("Cannot find template {}", grp->name);
FatalError("Cannot find template {}", grp.name);
}
DumpLine(template_item, grp, default_grp, _stored_output);
DumpLine(template_item, &grp, default_grp, _stored_output);
if (validation_grp != nullptr) {
IniItem *validation_item = validation_grp->GetItem(grp->name); // Find template value.
const IniItem *validation_item = validation_grp->GetItem(grp.name); // Find template value.
if (validation_item != nullptr && validation_item->value.has_value()) {
DumpLine(validation_item, grp, default_grp, _post_amble_output);
DumpLine(validation_item, &grp, default_grp, _post_amble_output);
}
}
}
@ -430,11 +415,14 @@ static const OptionData _opts[] = {
*/
static void ProcessIniFile(const char *fname)
{
IniLoadFile *ini_data = LoadIniFile(fname);
DumpGroup(ini_data, PREAMBLE_GROUP_NAME);
DumpSections(ini_data);
DumpGroup(ini_data, POSTAMBLE_GROUP_NAME);
delete ini_data;
static const IniLoadFile::IniGroupNameList seq_groups = {PREAMBLE_GROUP_NAME, POSTAMBLE_GROUP_NAME};
SettingsIniFile ini{{}, seq_groups};
ini.LoadFromDisk(fname, NO_DIRECTORY);
DumpGroup(ini, PREAMBLE_GROUP_NAME);
DumpSections(ini);
DumpGroup(ini, POSTAMBLE_GROUP_NAME);
}
/**

View File

@ -98,7 +98,7 @@ SpriteFile &OpenCachedSpriteFile(const std::string &filename, Subdirectory subdi
{
SpriteFile *file = GetCachedSpriteFileByName(filename);
if (file == nullptr) {
file = _sprite_files.emplace_back(new SpriteFile(filename, subdir, palette_remap)).get();
file = _sprite_files.insert(std::end(_sprite_files), std::make_unique<SpriteFile>(filename, subdir, palette_remap))->get();
} else {
file->SeekToBegin();
}

View File

@ -518,16 +518,16 @@ CargoTypes GetEmptyMask(const Station *st)
}
/**
* Items contains the two cargo names that are to be accepted or rejected.
* msg is the string id of the message to display.
* Add news item for when a station changes which cargoes it accepts.
* @param st Station of cargo change.
* @param cargoes Bit mask of cargo types to list.
* @param reject True iff the station rejects the cargo types.
*/
static void ShowRejectOrAcceptNews(const Station *st, uint num_items, CargoID *cargo, StringID msg)
static void ShowRejectOrAcceptNews(const Station *st, CargoTypes cargoes, bool reject)
{
for (uint i = 0; i < num_items; i++) {
SetDParam(i + 1, CargoSpec::Get(cargo[i])->name);
}
SetDParam(0, st->index);
SetDParam(1, cargoes);
StringID msg = reject ? STR_NEWS_STATION_NO_LONGER_ACCEPTS_CARGO_LIST : STR_NEWS_STATION_NOW_ACCEPTS_CARGO_LIST;
AddNewsItem(msg, NT_ACCEPTANCE, NF_INCOLOUR | NF_SMALL, NR_STATION, st->index);
}
@ -651,41 +651,13 @@ void UpdateStationAcceptance(Station *st, bool show_msg)
/* show a message to report that the acceptance was changed? */
if (show_msg && st->owner == _local_company && st->IsInUse()) {
/* List of accept and reject strings for different number of
* cargo types */
static const StringID accept_msg[] = {
STR_NEWS_STATION_NOW_ACCEPTS_CARGO,
STR_NEWS_STATION_NOW_ACCEPTS_CARGO_AND_CARGO,
};
static const StringID reject_msg[] = {
STR_NEWS_STATION_NO_LONGER_ACCEPTS_CARGO,
STR_NEWS_STATION_NO_LONGER_ACCEPTS_CARGO_OR_CARGO,
};
/* Array of accepted and rejected cargo types */
CargoID accepts[2] = { CT_INVALID, CT_INVALID };
CargoID rejects[2] = { CT_INVALID, CT_INVALID };
uint num_acc = 0;
uint num_rej = 0;
/* Test each cargo type to see if its acceptance has changed */
for (CargoID i = 0; i < NUM_CARGO; i++) {
if (HasBit(new_acc, i)) {
if (!HasBit(old_acc, i) && num_acc < lengthof(accepts)) {
/* New cargo is accepted */
accepts[num_acc++] = i;
}
} else {
if (HasBit(old_acc, i) && num_rej < lengthof(rejects)) {
/* Old cargo is no longer accepted */
rejects[num_rej++] = i;
}
}
}
/* Combine old and new masks to get changes */
CargoTypes accepts = new_acc & ~old_acc;
CargoTypes rejects = ~new_acc & old_acc;
/* Show news message if there are any changes */
if (num_acc > 0) ShowRejectOrAcceptNews(st, num_acc, accepts, accept_msg[num_acc - 1]);
if (num_rej > 0) ShowRejectOrAcceptNews(st, num_rej, rejects, reject_msg[num_rej - 1]);
if (accepts != 0) ShowRejectOrAcceptNews(st, accepts, false);
if (rejects != 0) ShowRejectOrAcceptNews(st, rejects, true);
}
/* redraw the station view since acceptance changed */

View File

@ -253,11 +253,11 @@ protected:
for (const StoryPage *p : this->story_pages) {
bool current_page = p->index == this->selected_page_id;
if (!p->title.empty()) {
list.emplace_back(new DropDownListStringItem(p->title, p->index, current_page));
list.push_back(std::make_unique<DropDownListStringItem>(p->title, p->index, current_page));
} else {
/* No custom title => use a generic page title with page number. */
SetDParam(0, page_num);
list.emplace_back(new DropDownListStringItem(STR_STORY_BOOK_GENERIC_PAGE_ITEM, p->index, current_page));
list.push_back(std::make_unique<DropDownListStringItem>(STR_STORY_BOOK_GENERIC_PAGE_ITEM, p->index, current_page));
}
page_num++;
}

View File

@ -528,8 +528,7 @@ void TextfileWindow::AfterLoadMarkdown()
DropDownList list;
for (size_t line : this->jumplist) {
SetDParamStr(0, this->lines[line].text);
DropDownListStringItem *item = new DropDownListStringItem(STR_TEXTFILE_JUMPLIST_ITEM, (int)line, false);
list.emplace_back(item);
list.push_back(std::make_unique<DropDownListStringItem>(STR_TEXTFILE_JUMPLIST_ITEM, (int)line, false));
}
ShowDropDownList(this, std::move(list), -1, widget);
break;

View File

@ -207,7 +207,7 @@ static void PopupMainToolbMenu(Window *w, int widget, StringID string, int count
{
DropDownList list;
for (int i = 0; i < count; i++) {
list.emplace_back(new DropDownListStringItem(string + i, i, false));
list.push_back(std::make_unique<DropDownListStringItem>(string + i, i, false));
}
PopupMainToolbMenu(w, widget, std::move(list), 0);
}
@ -232,24 +232,24 @@ static void PopupMainCompanyToolbMenu(Window *w, int widget, int grey = 0)
if (!_networking) break;
/* Add the client list button for the companies menu */
list.emplace_back(new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_CLIENT_LIST, CTMN_CLIENT_LIST, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_NETWORK_COMPANY_LIST_CLIENT_LIST, CTMN_CLIENT_LIST, false));
if (_local_company != COMPANY_SPECTATOR) {
list.emplace_back(new DropDownListStringItem(STR_NETWORK_COMPANY_LIST_SPECTATE, CTMN_SPECTATE, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_NETWORK_COMPANY_LIST_SPECTATE, CTMN_SPECTATE, false));
}
break;
case WID_TN_STORY:
list.emplace_back(new DropDownListStringItem(STR_STORY_BOOK_SPECTATOR, CTMN_SPECTATOR, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_STORY_BOOK_SPECTATOR, CTMN_SPECTATOR, false));
break;
case WID_TN_GOAL:
list.emplace_back(new DropDownListStringItem(STR_GOALS_SPECTATOR, CTMN_SPECTATOR, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_GOALS_SPECTATOR, CTMN_SPECTATOR, false));
break;
}
for (CompanyID c = COMPANY_FIRST; c < MAX_COMPANIES; c++) {
if (!Company::IsValidID(c)) continue;
list.emplace_back(new DropDownListCompanyItem(c, false, HasBit(grey, c)));
list.push_back(std::make_unique<DropDownListCompanyItem>(c, false, HasBit(grey, c)));
}
PopupMainToolbMenu(w, widget, std::move(list), _local_company == COMPANY_SPECTATOR ? (widget == WID_TN_COMPANIES ? CTMN_CLIENT_LIST : CTMN_SPECTATOR) : (int)_local_company);
@ -325,27 +325,27 @@ enum OptionMenuEntries {
static CallBackFunction ToolbarOptionsClick(Window *w)
{
DropDownList list;
list.emplace_back(new DropDownListStringItem(STR_SETTINGS_MENU_GAME_OPTIONS, OME_GAMEOPTIONS, false));
list.emplace_back(new DropDownListStringItem(STR_SETTINGS_MENU_CONFIG_SETTINGS_TREE, OME_SETTINGS, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_SETTINGS_MENU_GAME_OPTIONS, OME_GAMEOPTIONS, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_SETTINGS_MENU_CONFIG_SETTINGS_TREE, OME_SETTINGS, false));
/* Changes to the per-AI settings don't get send from the server to the clients. Clients get
* the settings once they join but never update it. As such don't show the window at all
* to network clients. */
if (!_networking || _network_server) {
list.emplace_back(new DropDownListStringItem(STR_SETTINGS_MENU_AI_SETTINGS, OME_AI_SETTINGS, false));
list.emplace_back(new DropDownListStringItem(STR_SETTINGS_MENU_GAMESCRIPT_SETTINGS, OME_GAMESCRIPT_SETTINGS, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_SETTINGS_MENU_AI_SETTINGS, OME_AI_SETTINGS, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_SETTINGS_MENU_GAMESCRIPT_SETTINGS, OME_GAMESCRIPT_SETTINGS, false));
}
list.emplace_back(new DropDownListStringItem(STR_SETTINGS_MENU_NEWGRF_SETTINGS, OME_NEWGRFSETTINGS, false));
list.emplace_back(new DropDownListStringItem(STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS, OME_TRANSPARENCIES, false));
list.emplace_back(new DropDownListItem(-1, false));
list.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED, OME_SHOW_TOWNNAMES, false, HasBit(_display_opt, DO_SHOW_TOWN_NAMES)));
list.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_STATION_NAMES_DISPLAYED, OME_SHOW_STATIONNAMES, false, HasBit(_display_opt, DO_SHOW_STATION_NAMES)));
list.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_WAYPOINTS_DISPLAYED, OME_SHOW_WAYPOINTNAMES, false, HasBit(_display_opt, DO_SHOW_WAYPOINT_NAMES)));
list.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_SIGNS_DISPLAYED, OME_SHOW_SIGNS, false, HasBit(_display_opt, DO_SHOW_SIGNS)));
list.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_SHOW_COMPETITOR_SIGNS, OME_SHOW_COMPETITOR_SIGNS, false, HasBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS)));
list.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_ANIMATION, OME_FULL_ANIMATION, false, HasBit(_display_opt, DO_FULL_ANIMATION)));
list.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_FULL_DETAIL, OME_FULL_DETAILS, false, HasBit(_display_opt, DO_FULL_DETAIL)));
list.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_BUILDINGS, OME_TRANSPARENTBUILDINGS, false, IsTransparencySet(TO_HOUSES)));
list.emplace_back(new DropDownListCheckedItem(STR_SETTINGS_MENU_TRANSPARENT_SIGNS, OME_SHOW_STATIONSIGNS, false, IsTransparencySet(TO_SIGNS)));
list.push_back(std::make_unique<DropDownListStringItem>(STR_SETTINGS_MENU_NEWGRF_SETTINGS, OME_NEWGRFSETTINGS, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_SETTINGS_MENU_TRANSPARENCY_OPTIONS, OME_TRANSPARENCIES, false));
list.push_back(std::make_unique<DropDownListItem>(-1, false));
list.push_back(std::make_unique<DropDownListCheckedItem>(STR_SETTINGS_MENU_TOWN_NAMES_DISPLAYED, OME_SHOW_TOWNNAMES, false, HasBit(_display_opt, DO_SHOW_TOWN_NAMES)));
list.push_back(std::make_unique<DropDownListCheckedItem>(STR_SETTINGS_MENU_STATION_NAMES_DISPLAYED, OME_SHOW_STATIONNAMES, false, HasBit(_display_opt, DO_SHOW_STATION_NAMES)));
list.push_back(std::make_unique<DropDownListCheckedItem>(STR_SETTINGS_MENU_WAYPOINTS_DISPLAYED, OME_SHOW_WAYPOINTNAMES, false, HasBit(_display_opt, DO_SHOW_WAYPOINT_NAMES)));
list.push_back(std::make_unique<DropDownListCheckedItem>(STR_SETTINGS_MENU_SIGNS_DISPLAYED, OME_SHOW_SIGNS, false, HasBit(_display_opt, DO_SHOW_SIGNS)));
list.push_back(std::make_unique<DropDownListCheckedItem>(STR_SETTINGS_MENU_SHOW_COMPETITOR_SIGNS, OME_SHOW_COMPETITOR_SIGNS, false, HasBit(_display_opt, DO_SHOW_COMPETITOR_SIGNS)));
list.push_back(std::make_unique<DropDownListCheckedItem>(STR_SETTINGS_MENU_FULL_ANIMATION, OME_FULL_ANIMATION, false, HasBit(_display_opt, DO_FULL_ANIMATION)));
list.push_back(std::make_unique<DropDownListCheckedItem>(STR_SETTINGS_MENU_FULL_DETAIL, OME_FULL_DETAILS, false, HasBit(_display_opt, DO_FULL_DETAIL)));
list.push_back(std::make_unique<DropDownListCheckedItem>(STR_SETTINGS_MENU_TRANSPARENT_BUILDINGS, OME_TRANSPARENTBUILDINGS, false, IsTransparencySet(TO_HOUSES)));
list.push_back(std::make_unique<DropDownListCheckedItem>(STR_SETTINGS_MENU_TRANSPARENT_SIGNS, OME_SHOW_STATIONSIGNS, false, IsTransparencySet(TO_SIGNS)));
ShowDropDownList(w, std::move(list), 0, WID_TN_SETTINGS, 140, true);
if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
@ -475,10 +475,10 @@ enum MapMenuEntries {
static CallBackFunction ToolbarMapClick(Window *w)
{
DropDownList list;
list.emplace_back(new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD, MME_SHOW_SMALLMAP, false));
list.emplace_back(new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEWPORT, MME_SHOW_EXTRAVIEWPORTS, false));
list.emplace_back(new DropDownListStringItem(STR_MAP_MENU_LINGRAPH_LEGEND, MME_SHOW_LINKGRAPH, false));
list.emplace_back(new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST, MME_SHOW_SIGNLISTS, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_MAP_MENU_MAP_OF_WORLD, MME_SHOW_SMALLMAP, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_MAP_MENU_EXTRA_VIEWPORT, MME_SHOW_EXTRAVIEWPORTS, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_MAP_MENU_LINGRAPH_LEGEND, MME_SHOW_LINKGRAPH, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_MAP_MENU_SIGN_LIST, MME_SHOW_SIGNLISTS, false));
PopupMainToolbMenu(w, WID_TN_SMALL_MAP, std::move(list), 0);
return CBF_NONE;
}
@ -486,11 +486,11 @@ static CallBackFunction ToolbarMapClick(Window *w)
static CallBackFunction ToolbarScenMapTownDir(Window *w)
{
DropDownList list;
list.emplace_back(new DropDownListStringItem(STR_MAP_MENU_MAP_OF_WORLD, MME_SHOW_SMALLMAP, false));
list.emplace_back(new DropDownListStringItem(STR_MAP_MENU_EXTRA_VIEWPORT, MME_SHOW_EXTRAVIEWPORTS, false));
list.emplace_back(new DropDownListStringItem(STR_MAP_MENU_SIGN_LIST, MME_SHOW_SIGNLISTS, false));
list.emplace_back(new DropDownListStringItem(STR_TOWN_MENU_TOWN_DIRECTORY, MME_SHOW_TOWNDIRECTORY, false));
list.emplace_back(new DropDownListStringItem(STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY, MME_SHOW_INDUSTRYDIRECTORY, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_MAP_MENU_MAP_OF_WORLD, MME_SHOW_SMALLMAP, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_MAP_MENU_EXTRA_VIEWPORT, MME_SHOW_EXTRAVIEWPORTS, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_MAP_MENU_SIGN_LIST, MME_SHOW_SIGNLISTS, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_TOWN_MENU_TOWN_DIRECTORY, MME_SHOW_TOWNDIRECTORY, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_INDUSTRY_MENU_INDUSTRY_DIRECTORY, MME_SHOW_INDUSTRYDIRECTORY, false));
PopupMainToolbMenu(w, WID_TE_SMALL_MAP, std::move(list), 0);
return CBF_NONE;
}
@ -693,13 +693,13 @@ static const int LTMN_HIGHSCORE = -9; ///< Show highscrore table
static void AddDropDownLeagueTableOptions(DropDownList &list) {
if (LeagueTable::GetNumItems() > 0) {
for (LeagueTable *lt : LeagueTable::Iterate()) {
list.emplace_back(new DropDownListStringItem(lt->title, lt->index, false));
list.push_back(std::make_unique<DropDownListStringItem>(lt->title, lt->index, false));
}
} else {
list.emplace_back(new DropDownListStringItem(STR_GRAPH_MENU_COMPANY_LEAGUE_TABLE, LTMN_PERFORMANCE_LEAGUE, false));
list.emplace_back(new DropDownListStringItem(STR_GRAPH_MENU_DETAILED_PERFORMANCE_RATING, LTMN_PERFORMANCE_RATING, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_GRAPH_MENU_COMPANY_LEAGUE_TABLE, LTMN_PERFORMANCE_LEAGUE, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_GRAPH_MENU_DETAILED_PERFORMANCE_RATING, LTMN_PERFORMANCE_RATING, false));
if (!_networking) {
list.emplace_back(new DropDownListStringItem(STR_GRAPH_MENU_HIGHSCORE, LTMN_HIGHSCORE, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_GRAPH_MENU_HIGHSCORE, LTMN_HIGHSCORE, false));
}
}
}
@ -708,12 +708,12 @@ static CallBackFunction ToolbarGraphsClick(Window *w)
{
DropDownList list;
list.emplace_back(new DropDownListStringItem(STR_GRAPH_MENU_OPERATING_PROFIT_GRAPH, GRMN_OPERATING_PROFIT_GRAPH, false));
list.emplace_back(new DropDownListStringItem(STR_GRAPH_MENU_INCOME_GRAPH, GRMN_INCOME_GRAPH, false));
list.emplace_back(new DropDownListStringItem(STR_GRAPH_MENU_DELIVERED_CARGO_GRAPH, GRMN_DELIVERED_CARGO_GRAPH, false));
list.emplace_back(new DropDownListStringItem(STR_GRAPH_MENU_PERFORMANCE_HISTORY_GRAPH, GRMN_PERFORMANCE_HISTORY_GRAPH, false));
list.emplace_back(new DropDownListStringItem(STR_GRAPH_MENU_COMPANY_VALUE_GRAPH, GRMN_COMPANY_VALUE_GRAPH, false));
list.emplace_back(new DropDownListStringItem(STR_GRAPH_MENU_CARGO_PAYMENT_RATES, GRMN_CARGO_PAYMENT_RATES, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_GRAPH_MENU_OPERATING_PROFIT_GRAPH, GRMN_OPERATING_PROFIT_GRAPH, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_GRAPH_MENU_INCOME_GRAPH, GRMN_INCOME_GRAPH, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_GRAPH_MENU_DELIVERED_CARGO_GRAPH, GRMN_DELIVERED_CARGO_GRAPH, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_GRAPH_MENU_PERFORMANCE_HISTORY_GRAPH, GRMN_PERFORMANCE_HISTORY_GRAPH, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_GRAPH_MENU_COMPANY_VALUE_GRAPH, GRMN_COMPANY_VALUE_GRAPH, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_GRAPH_MENU_CARGO_PAYMENT_RATES, GRMN_CARGO_PAYMENT_RATES, false));
if (_toolbar_mode != TB_NORMAL) AddDropDownLeagueTableOptions(list);
@ -974,7 +974,7 @@ static CallBackFunction MenuClickBuildTram(int index)
static CallBackFunction ToolbarBuildWaterClick(Window *w)
{
DropDownList list;
list.emplace_back(new DropDownListIconItem(SPR_IMG_BUILD_CANAL, PAL_NONE, STR_WATERWAYS_MENU_WATERWAYS_CONSTRUCTION, 0, false));
list.push_back(std::make_unique<DropDownListIconItem>(SPR_IMG_BUILD_CANAL, PAL_NONE, STR_WATERWAYS_MENU_WATERWAYS_CONSTRUCTION, 0, false));
ShowDropDownList(w, std::move(list), 0, WID_TN_WATER, 140, true);
if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
return CBF_NONE;
@ -996,7 +996,7 @@ static CallBackFunction MenuClickBuildWater(int)
static CallBackFunction ToolbarBuildAirClick(Window *w)
{
DropDownList list;
list.emplace_back(new DropDownListIconItem(SPR_IMG_AIRPORT, PAL_NONE, STR_AIRCRAFT_MENU_AIRPORT_CONSTRUCTION, 0, false));
list.push_back(std::make_unique<DropDownListIconItem>(SPR_IMG_AIRPORT, PAL_NONE, STR_AIRCRAFT_MENU_AIRPORT_CONSTRUCTION, 0, false));
ShowDropDownList(w, std::move(list), 0, WID_TN_AIR, 140, true);
if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
return CBF_NONE;
@ -1018,9 +1018,9 @@ static CallBackFunction MenuClickBuildAir(int)
static CallBackFunction ToolbarForestClick(Window *w)
{
DropDownList list;
list.emplace_back(new DropDownListIconItem(SPR_IMG_LANDSCAPING, PAL_NONE, STR_LANDSCAPING_MENU_LANDSCAPING, 0, false));
list.emplace_back(new DropDownListIconItem(SPR_IMG_PLANTTREES, PAL_NONE, STR_LANDSCAPING_MENU_PLANT_TREES, 1, false));
list.emplace_back(new DropDownListIconItem(SPR_IMG_SIGN, PAL_NONE, STR_LANDSCAPING_MENU_PLACE_SIGN, 2, false));
list.push_back(std::make_unique<DropDownListIconItem>(SPR_IMG_LANDSCAPING, PAL_NONE, STR_LANDSCAPING_MENU_LANDSCAPING, 0, false));
list.push_back(std::make_unique<DropDownListIconItem>(SPR_IMG_PLANTTREES, PAL_NONE, STR_LANDSCAPING_MENU_PLANT_TREES, 1, false));
list.push_back(std::make_unique<DropDownListIconItem>(SPR_IMG_SIGN, PAL_NONE, STR_LANDSCAPING_MENU_PLACE_SIGN, 2, false));
ShowDropDownList(w, std::move(list), 0, WID_TN_LANDSCAPE, 100, true);
if (_settings_client.sound.click_beep) SndPlayFx(SND_15_BEEP);
return CBF_NONE;

View File

@ -447,14 +447,15 @@ void DrawTrainDetails(const Train *v, const Rect &r, int vscroll_pos, uint16_t v
/* Indent the total cargo capacity details */
Rect ir = r.Indent(WidgetDimensions::scaled.hsep_indent, rtl);
for (CargoID i = 0; i < NUM_CARGO; i++) {
if (max_cargo[i] > 0 && --vscroll_pos < 0 && vscroll_pos > -vscroll_cap) {
SetDParam(0, i); // {CARGO} #1
SetDParam(1, act_cargo[i]); // {CARGO} #2
SetDParam(2, i); // {SHORTCARGO} #1
SetDParam(3, max_cargo[i]); // {SHORTCARGO} #2
for (const CargoSpec *cs : _sorted_cargo_specs) {
CargoID cid = cs->Index();
if (max_cargo[cid] > 0 && --vscroll_pos < 0 && vscroll_pos > -vscroll_cap) {
SetDParam(0, cid); // {CARGO} #1
SetDParam(1, act_cargo[cid]); // {CARGO} #2
SetDParam(2, cid); // {SHORTCARGO} #1
SetDParam(3, max_cargo[cid]); // {SHORTCARGO} #2
SetDParam(4, _settings_game.vehicle.freight_trains);
DrawString(ir.left, ir.right, y + text_y_offset, FreightWagonMult(i) > 1 ? STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY_MULT : STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY);
DrawString(ir.left, ir.right, y + text_y_offset, FreightWagonMult(cid) > 1 ? STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY_MULT : STR_VEHICLE_DETAILS_TRAIN_TOTAL_CAPACITY);
y += line_height;
}
}

View File

@ -399,15 +399,15 @@ DropDownList BaseVehicleListWindow::BuildActionDropdownList(bool show_autoreplac
{
DropDownList list;
if (show_autoreplace) list.emplace_back(new DropDownListStringItem(STR_VEHICLE_LIST_REPLACE_VEHICLES, ADI_REPLACE, false));
list.emplace_back(new DropDownListStringItem(STR_VEHICLE_LIST_SEND_FOR_SERVICING, ADI_SERVICE, false));
list.emplace_back(new DropDownListStringItem(this->vehicle_depot_name[this->vli.vtype], ADI_DEPOT, false));
if (show_autoreplace) list.push_back(std::make_unique<DropDownListStringItem>(STR_VEHICLE_LIST_REPLACE_VEHICLES, ADI_REPLACE, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_VEHICLE_LIST_SEND_FOR_SERVICING, ADI_SERVICE, false));
list.push_back(std::make_unique<DropDownListStringItem>(this->vehicle_depot_name[this->vli.vtype], ADI_DEPOT, false));
if (show_group) {
list.emplace_back(new DropDownListStringItem(STR_GROUP_ADD_SHARED_VEHICLE, ADI_ADD_SHARED, false));
list.emplace_back(new DropDownListStringItem(STR_GROUP_REMOVE_ALL_VEHICLES, ADI_REMOVE_ALL, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_GROUP_ADD_SHARED_VEHICLE, ADI_ADD_SHARED, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_GROUP_REMOVE_ALL_VEHICLES, ADI_REMOVE_ALL, false));
} else if (show_create) {
list.emplace_back(new DropDownListStringItem(STR_VEHICLE_LIST_CREATE_GROUP, ADI_CREATE_GROUP, false));
list.push_back(std::make_unique<DropDownListStringItem>(STR_VEHICLE_LIST_CREATE_GROUP, ADI_CREATE_GROUP, false));
}
return list;
@ -550,18 +550,18 @@ struct RefitOption {
}
};
typedef std::vector<RefitOption> SubtypeList; ///< List of refit subtypes associated to a cargo.
using RefitOptions = std::map<CargoID, std::vector<RefitOption>, CargoIDComparator>; ///< Available refit options (subtype and string) associated with each cargo type.
/**
* Draw the list of available refit options for a consist and highlight the selected refit option (if any).
* @param list List of subtype options for each (sorted) cargo.
* @param sel Selected refit cargo-type in the window
* @param refits Available refit options for each (sorted) cargo.
* @param sel Selected refit option in the window
* @param pos Position of the selected item in caller widow
* @param rows Number of rows(capacity) in caller window
* @param delta Step height in caller window
* @param r Rectangle of the matrix widget.
*/
static void DrawVehicleRefitWindow(const SubtypeList list[NUM_CARGO], const int sel[2], uint pos, uint rows, uint delta, const Rect &r)
static void DrawVehicleRefitWindow(const RefitOptions &refits, const RefitOption *sel, uint pos, uint rows, uint delta, const Rect &r)
{
Rect ir = r.Shrink(WidgetDimensions::scaled.matrix);
uint current = 0;
@ -578,12 +578,13 @@ static void DrawVehicleRefitWindow(const SubtypeList list[NUM_CARGO], const int
Rect tr = ir.Indent(iconwidth + WidgetDimensions::scaled.hsep_wide, rtl);
/* Draw the list of subtypes for each cargo, and find the selected refit option (by its position). */
for (uint i = 0; current < pos + rows && i < NUM_CARGO; i++) {
for (uint j = 0; current < pos + rows && j < list[i].size(); j++) {
const RefitOption &refit = list[i][j];
for (const auto &pair : refits) {
bool has_subtypes = pair.second.size() > 1;
for (const RefitOption &refit : pair.second) {
if (current >= pos + rows) break;
/* Hide subtypes if sel[0] does not match */
if (sel[0] != (int)i && refit.subtype != 0xFF) continue;
/* Hide subtypes if selected cargo type does not match */
if ((sel == nullptr || sel->cargo != refit.cargo) && refit.subtype != UINT8_MAX) continue;
/* Refit options with a position smaller than pos don't have to be drawn. */
if (current < pos) {
@ -591,19 +592,19 @@ static void DrawVehicleRefitWindow(const SubtypeList list[NUM_CARGO], const int
continue;
}
if (list[i].size() > 1) {
if (refit.subtype != 0xFF) {
if (has_subtypes) {
if (refit.subtype != UINT8_MAX) {
/* Draw tree lines */
int ycenter = tr.top + FONT_HEIGHT_NORMAL / 2;
GfxDrawLine(iconcenter, tr.top - WidgetDimensions::scaled.matrix.top, iconcenter, j == list[i].size() - 1 ? ycenter : tr.top - WidgetDimensions::scaled.matrix.top + delta - 1, linecolour);
GfxDrawLine(iconcenter, tr.top - WidgetDimensions::scaled.matrix.top, iconcenter, (&refit == &pair.second.back()) ? ycenter : tr.top - WidgetDimensions::scaled.matrix.top + delta - 1, linecolour);
GfxDrawLine(iconcenter, ycenter, iconinner, ycenter, linecolour);
} else {
/* Draw expand/collapse icon */
DrawSprite(sel[0] == (int)i ? SPR_CIRCLE_UNFOLDED : SPR_CIRCLE_FOLDED, PAL_NONE, iconleft, tr.top + (FONT_HEIGHT_NORMAL - iconheight) / 2);
DrawSprite((sel != nullptr && sel->cargo == refit.cargo) ? SPR_CIRCLE_UNFOLDED : SPR_CIRCLE_FOLDED, PAL_NONE, iconleft, tr.top + (FONT_HEIGHT_NORMAL - iconheight) / 2);
}
}
TextColour colour = (sel[0] == (int)i && (uint)sel[1] == j) ? TC_WHITE : TC_BLACK;
TextColour colour = (sel != nullptr && sel->cargo == refit.cargo && sel->subtype == refit.subtype) ? TC_WHITE : TC_BLACK;
/* Get the cargo name. */
SetDParam(0, CargoSpec::Get(refit.cargo)->name);
SetDParam(1, refit.string);
@ -617,9 +618,8 @@ static void DrawVehicleRefitWindow(const SubtypeList list[NUM_CARGO], const int
/** Refit cargo window. */
struct RefitWindow : public Window {
int sel[2]; ///< Index in refit options, sel[0] == -1 if nothing is selected.
RefitOption *cargo; ///< Refit option selected by #sel.
SubtypeList list[NUM_CARGO]; ///< List of refit subtypes available for each sorted cargo.
const RefitOption *selected_refit; ///< Selected refit option.
RefitOptions refit_list; ///< List of refit subtypes available for each sorted cargo.
VehicleOrderID order; ///< If not #INVALID_VEH_ORDER_ID, selection is part of a refit order (rather than execute directly).
uint information_width; ///< Width required for correctly displaying all cargoes in the information panel.
Scrollbar *vscroll; ///< The main scrollbar.
@ -638,7 +638,12 @@ struct RefitWindow : public Window {
*/
void BuildRefitList()
{
for (uint i = 0; i < NUM_CARGO; i++) this->list[i].clear();
/* Store the currently selected RefitOption. */
std::optional<RefitOption> current_refit_option;
if (this->selected_refit != nullptr) current_refit_option = *(this->selected_refit);
this->selected_refit = nullptr;
this->refit_list.clear();
Vehicle *v = Vehicle::Get(this->window_number);
/* Check only the selected vehicles. */
@ -657,19 +662,16 @@ struct RefitWindow : public Window {
if (this->auto_refit && !HasBit(e->info.misc_flags, EF_AUTO_REFIT)) continue;
/* Loop through all cargoes in the refit mask */
int current_index = 0;
for (const auto &cs : _sorted_cargo_specs) {
CargoID cid = cs->Index();
/* Skip cargo type if it's not listed */
if (!HasBit(cmask, cid)) {
current_index++;
continue;
}
if (!HasBit(cmask, cid)) continue;
bool first_vehicle = this->list[current_index].size() == 0;
auto &list = this->refit_list[cid];
bool first_vehicle = list.size() == 0;
if (first_vehicle) {
/* Keeping the current subtype is always an option. It also serves as the option in case of no subtypes */
this->list[current_index].push_back({cid, 0xFF, STR_EMPTY});
list.push_back({cid, UINT8_MAX, STR_EMPTY});
}
/* Check the vehicle's callback mask for cargo suffixes.
@ -701,16 +703,15 @@ struct RefitWindow : public Window {
option.cargo = cid;
option.subtype = refit_cyc;
option.string = subtype;
include(this->list[current_index], option);
include(list, option);
} else {
/* Intersect the subtypes of earlier vehicles with the subtypes of this vehicle */
if (subtype == STR_EMPTY) {
/* No more subtypes for this vehicle, delete all subtypes >= refit_cyc */
SubtypeList &l = this->list[current_index];
/* 0xFF item is in front, other subtypes are sorted. So just truncate the list in the right spot */
for (uint i = 1; i < l.size(); i++) {
if (l[i].subtype >= refit_cyc) {
l.resize(i);
/* UINT8_MAX item is in front, other subtypes are sorted. So just truncate the list in the right spot */
for (uint i = 1; i < list.size(); i++) {
if (list[i].subtype >= refit_cyc) {
list.resize(i);
break;
}
}
@ -718,11 +719,10 @@ struct RefitWindow : public Window {
} else {
/* Check whether the subtype matches with the subtype of earlier vehicles. */
uint pos = 1;
SubtypeList &l = this->list[current_index];
while (pos < l.size() && l[pos].subtype != refit_cyc) pos++;
if (pos < l.size() && l[pos].string != subtype) {
while (pos < list.size() && list[pos].subtype != refit_cyc) pos++;
if (pos < list.size() && list[pos].string != subtype) {
/* String mismatch, remove item keeping the order */
l.erase(l.begin() + pos);
list.erase(list.begin() + pos);
}
}
}
@ -736,9 +736,23 @@ struct RefitWindow : public Window {
v->First()->InvalidateNewGRFCache();
v->InvalidateNewGRFCache();
}
current_index++;
}
} while (v->IsGroundVehicle() && (v = v->Next()) != nullptr);
/* Restore the previously selected RefitOption. */
if (current_refit_option.has_value()) {
for (const auto &pair : this->refit_list) {
for (const auto &refit : pair.second) {
if (refit.cargo == current_refit_option->cargo && refit.subtype == current_refit_option->subtype) {
this->selected_refit = &refit;
break;
}
}
if (this->selected_refit != nullptr) break;
}
}
this->SetWidgetDisabledState(WID_VR_REFIT, this->selected_refit == nullptr);
}
/**
@ -746,24 +760,22 @@ struct RefitWindow : public Window {
*/
void RefreshScrollbar()
{
uint scroll_row = 0;
uint row = 0;
size_t scroll_row = 0;
size_t rows = 0;
CargoID cargo = this->selected_refit == nullptr ? (CargoID)CT_INVALID : this->selected_refit->cargo;
for (uint i = 0; i < NUM_CARGO; i++) {
for (uint j = 0; j < this->list[i].size(); j++) {
const RefitOption &refit = this->list[i][j];
/* Hide subtypes if sel[0] does not match */
if (this->sel[0] != (int)i && refit.subtype != 0xFF) continue;
if (this->sel[0] == (int)i && (uint)this->sel[1] == j) scroll_row = row;
row++;
for (const auto &pair : this->refit_list) {
if (pair.first == cargo) {
/* selected_refit points to an element in the vector so no need to search for it. */
scroll_row = rows + (this->selected_refit - pair.second.data());
rows += pair.second.size();
} else {
rows++; /* Unselected cargo type is collapsed into one row. */
}
}
this->vscroll->SetCount(row);
if (scroll_row < row) this->vscroll->ScrollTowards(scroll_row);
this->vscroll->SetCount(rows);
this->vscroll->ScrollTowards(static_cast<int>(scroll_row));
}
/**
@ -774,45 +786,24 @@ struct RefitWindow : public Window {
{
uint row = 0;
for (uint i = 0; i < NUM_CARGO; i++) {
for (uint j = 0; j < this->list[i].size(); j++) {
const RefitOption &refit = this->list[i][j];
/* Hide subtypes if sel[0] does not match */
if (this->sel[0] != (int)i && refit.subtype != 0xFF) continue;
for (const auto &pair : refit_list) {
for (const RefitOption &refit : pair.second) {
if (row == click_row) {
this->sel[0] = i;
this->sel[1] = j;
this->selected_refit = &refit;
return;
}
row++;
/* If this cargo type is not already selected then its subtypes are not visible, so skip the rest. */
if (this->selected_refit == nullptr || this->selected_refit->cargo != refit.cargo) break;
}
}
this->sel[0] = -1;
this->sel[1] = 0;
}
/**
* Gets the #RefitOption placed in the selected index.
* @return Pointer to the #RefitOption currently in use.
*/
RefitOption *GetRefitOption()
{
if (this->sel[0] < 0) return nullptr;
SubtypeList &l = this->list[this->sel[0]];
if ((uint)this->sel[1] >= l.size()) return nullptr;
return &l[this->sel[1]];
/* No selection made */
this->selected_refit = nullptr;
}
RefitWindow(WindowDesc *desc, const Vehicle *v, VehicleOrderID order, bool auto_refit) : Window(desc)
{
this->sel[0] = -1;
this->sel[1] = 0;
this->auto_refit = auto_refit;
this->order = order;
this->CreateNestedTree();
@ -830,38 +821,14 @@ struct RefitWindow : public Window {
this->FinishInitNested(v->index);
this->owner = v->owner;
this->SetWidgetDisabledState(WID_VR_REFIT, this->sel[0] < 0);
this->SetWidgetDisabledState(WID_VR_REFIT, this->selected_refit == nullptr);
}
void OnInit() override
{
if (this->cargo != nullptr) {
/* Store the RefitOption currently in use. */
RefitOption current_refit_option = *(this->cargo);
/* Rebuild the refit list */
this->BuildRefitList();
this->sel[0] = -1;
this->sel[1] = 0;
this->cargo = nullptr;
for (uint i = 0; this->cargo == nullptr && i < NUM_CARGO; i++) {
for (uint j = 0; j < list[i].size(); j++) {
if (list[i][j] == current_refit_option) {
this->sel[0] = i;
this->sel[1] = j;
this->cargo = &list[i][j];
break;
}
}
}
this->SetWidgetDisabledState(WID_VR_REFIT, this->sel[0] < 0);
this->RefreshScrollbar();
} else {
/* Rebuild the refit list */
/* (Re)build the refit list */
this->OnInvalidateData(VIWD_CONSIST_CHANGED);
}
}
void OnPaint() override
{
@ -913,14 +880,14 @@ struct RefitWindow : public Window {
* @return INVALID_STRING_ID if there is no capacity. StringID to use in any other case.
* @post String parameters have been set.
*/
StringID GetCapacityString(RefitOption *option) const
StringID GetCapacityString(const RefitOption &option) const
{
assert(_current_company == _local_company);
auto [cost, refit_capacity, mail_capacity, cargo_capacities] = Command<CMD_REFIT_VEHICLE>::Do(DC_QUERY_COST, this->selected_vehicle, option->cargo, option->subtype, this->auto_refit, false, this->num_vehicles);
auto [cost, refit_capacity, mail_capacity, cargo_capacities] = Command<CMD_REFIT_VEHICLE>::Do(DC_QUERY_COST, this->selected_vehicle, option.cargo, option.subtype, this->auto_refit, false, this->num_vehicles);
if (cost.Failed()) return INVALID_STRING_ID;
SetDParam(0, option->cargo);
SetDParam(0, option.cargo);
SetDParam(1, refit_capacity);
Money money = cost.GetCost();
@ -1021,12 +988,12 @@ struct RefitWindow : public Window {
}
case WID_VR_MATRIX:
DrawVehicleRefitWindow(this->list, this->sel, this->vscroll->GetPosition(), this->vscroll->GetCapacity(), this->resize.step_height, r);
DrawVehicleRefitWindow(this->refit_list, this->selected_refit, this->vscroll->GetPosition(), this->vscroll->GetCapacity(), this->resize.step_height, r);
break;
case WID_VR_INFO:
if (this->cargo != nullptr) {
StringID string = this->GetCapacityString(this->cargo);
if (this->selected_refit != nullptr) {
StringID string = this->GetCapacityString(*this->selected_refit);
if (string != INVALID_STRING_ID) {
DrawStringMultiLine(r.Shrink(WidgetDimensions::scaled.framerect), string);
}
@ -1061,9 +1028,9 @@ struct RefitWindow : public Window {
uint max_width = 0;
/* Check the width of all cargo information strings. */
for (uint i = 0; i < NUM_CARGO; i++) {
for (uint j = 0; j < this->list[i].size(); j++) {
StringID string = this->GetCapacityString(&list[i][j]);
for (const auto &list : this->refit_list) {
for (const RefitOption &refit : list.second) {
StringID string = this->GetCapacityString(refit);
if (string != INVALID_STRING_ID) {
Dimension dim = GetStringBoundingBox(string);
max_width = std::max(dim.width, max_width);
@ -1080,7 +1047,6 @@ struct RefitWindow : public Window {
case 1: // A new cargo has been selected.
if (!gui_scope) break;
this->cargo = GetRefitOption();
this->RefreshScrollbar();
break;
}
@ -1168,7 +1134,7 @@ struct RefitWindow : public Window {
case WID_VR_MATRIX: { // listbox
this->SetSelection(this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_VR_MATRIX));
this->SetWidgetDisabledState(WID_VR_REFIT, this->sel[0] < 0);
this->SetWidgetDisabledState(WID_VR_REFIT, this->selected_refit == nullptr);
this->InvalidateData(1);
if (click_count == 1) break;
@ -1176,14 +1142,14 @@ struct RefitWindow : public Window {
}
case WID_VR_REFIT: // refit button
if (this->cargo != nullptr) {
if (this->selected_refit != nullptr) {
const Vehicle *v = Vehicle::Get(this->window_number);
if (this->order == INVALID_VEH_ORDER_ID) {
bool delete_window = this->selected_vehicle == v->index && this->num_vehicles == UINT8_MAX;
if (Command<CMD_REFIT_VEHICLE>::Post(GetCmdRefitVehMsg(v), v->tile, this->selected_vehicle, this->cargo->cargo, this->cargo->subtype, false, false, this->num_vehicles) && delete_window) this->Close();
if (Command<CMD_REFIT_VEHICLE>::Post(GetCmdRefitVehMsg(v), v->tile, this->selected_vehicle, this->selected_refit->cargo, this->selected_refit->subtype, false, false, this->num_vehicles) && delete_window) this->Close();
} else {
if (Command<CMD_ORDER_REFIT>::Post(v->tile, v->index, this->order, this->cargo->cargo)) this->Close();
if (Command<CMD_ORDER_REFIT>::Post(v->tile, v->index, this->order, this->selected_refit->cargo)) this->Close();
}
}
break;

View File

@ -464,7 +464,7 @@ void ShowDropDownMenu(Window *w, const StringID *strings, int selected, int butt
for (uint i = 0; strings[i] != INVALID_STRING_ID; i++) {
if (!HasBit(hidden_mask, i)) {
list.emplace_back(new DropDownListStringItem(strings[i], i, HasBit(disabled_mask, i)));
list.push_back(std::make_unique<DropDownListStringItem>(strings[i], i, HasBit(disabled_mask, i)));
}
}