Changeset - r24217:df2f5854f1e3
[Not reviewed]
master
0 15 0
Michael Lutz - 4 years ago 2020-05-17 21:32:06
michi@icosahedron.de
Codechange: Store base set related texts in std::strings.
15 files changed with 108 insertions and 91 deletions:
0 comments (0 inline, 0 general)
src/base_media_base.h
Show inline comments
 
@@ -12,12 +12,13 @@
 

	
 
#include "fileio_func.h"
 
#include "core/smallmap_type.hpp"
 
#include "gfx_type.h"
 
#include "textfile_type.h"
 
#include "textfile_gui.h"
 
#include <unordered_map>
 

	
 
/* Forward declare these; can't do 'struct X' in functions as older GCCs barf on that */
 
struct IniFile;
 
struct ContentInfo;
 

	
 
/** Structure holding filename and MD5 information about a single file */
 
@@ -43,24 +44,24 @@ struct MD5File {
 
 * @tparam T the real class we're going to be
 
 * @tparam Tnum_files the number of files in the set
 
 * @tparam Tsearch_in_tars whether to search in the tars or not
 
 */
 
template <class T, size_t Tnum_files, bool Tsearch_in_tars>
 
struct BaseSet {
 
	typedef SmallMap<const char *, const char *> TranslatedStrings;
 
	typedef std::unordered_map<std::string, std::string> TranslatedStrings;
 

	
 
	/** Number of files in this set */
 
	static const size_t NUM_FILES = Tnum_files;
 

	
 
	/** Whether to search in the tars or not. */
 
	static const bool SEARCH_IN_TARS = Tsearch_in_tars;
 

	
 
	/** Internal names of the files in this set. */
 
	static const char * const *file_names;
 

	
 
	const char *name;              ///< The name of the base set
 
	std::string name;              ///< The name of the base set
 
	TranslatedStrings description; ///< Description of the base set
 
	uint32 shortname;              ///< Four letter short variant of the name
 
	uint32 version;                ///< The version of this base set
 
	bool fallback;                 ///< This set is a fallback set, i.e. it should be used only as last resort
 

	
 
	MD5File files[NUM_FILES];      ///< All files part of this set
 
@@ -69,19 +70,12 @@ struct BaseSet {
 

	
 
	T *next;                       ///< The next base set in this list
 

	
 
	/** Free everything we allocated */
 
	~BaseSet()
 
	{
 
		free(this->name);
 

	
 
		for (auto &pair : this->description) {
 
			free(pair.first);
 
			free(pair.second);
 
		}
 

	
 
		for (uint i = 0; i < NUM_FILES; i++) {
 
			free(this->files[i].filename);
 
			free(this->files[i].missing_warning);
 
		}
 

	
 
		delete this->next;
 
@@ -113,26 +107,25 @@ struct BaseSet {
 
	 * It falls back to the first two characters of the ISO code in case
 
	 * no match could be made with the full ISO code. If even then the
 
	 * matching fails the default is returned.
 
	 * @param isocode the isocode to search for
 
	 * @return the description
 
	 */
 
	const char *GetDescription(const char *isocode = nullptr) const
 
	const char *GetDescription(const std::string &isocode) const
 
	{
 
		if (isocode != nullptr) {
 
		if (!isocode.empty()) {
 
			/* First the full ISO code */
 
			for (const auto &pair : this->description) {
 
				if (strcmp(pair.first, isocode) == 0) return pair.second;
 
			}
 
			auto desc = this->description.find(isocode);
 
			if (desc != this->description.end()) return desc->second.c_str();
 

	
 
			/* Then the first two characters */
 
			for (const auto &pair : this->description) {
 
				if (strncmp(pair.first, isocode, 2) == 0) return pair.second;
 
			}
 
			desc = this->description.find(isocode.substr(0, 2));
 
			if (desc != this->description.end()) return desc->second.c_str();
 
		}
 
		/* Then fall back */
 
		return this->description.front().second;
 
		return this->description.at(std::string{}).c_str();
 
	}
 

	
 
	/**
 
	 * Calculate and check the MD5 hash of the supplied file.
 
	 * @param file The file get the hash of.
 
	 * @param subdir The sub directory to get the files from.
 
@@ -180,13 +173,13 @@ protected:
 
	 * Get the extension that is used to identify this set.
 
	 * @return the extension
 
	 */
 
	static const char *GetExtension();
 
public:
 
	/** The set as saved in the config file. */
 
	static const char *ini_set;
 
	static std::string ini_set;
 

	
 
	/**
 
	 * Determine the graphics pack that has to be used.
 
	 * The one with the most correct files wins.
 
	 * @return true if a best set has been found.
 
	 */
 
@@ -200,13 +193,13 @@ public:
 
		uint num = fs.Scan(GetExtension(), Tbase_set::SEARCH_IN_TARS ? OLD_DATA_DIR : OLD_GM_DIR, Tbase_set::SEARCH_IN_TARS);
 
		return num + fs.Scan(GetExtension(), BASESET_DIR, Tbase_set::SEARCH_IN_TARS);
 
	}
 

	
 
	static Tbase_set *GetAvailableSets();
 

	
 
	static bool SetSet(const char *name);
 
	static bool SetSet(const std::string &name);
 
	static char *GetSetsList(char *p, const char *last);
 
	static int GetNumSets();
 
	static int GetIndexOfUsedSet();
 
	static const Tbase_set *GetSet(int index);
 
	static const Tbase_set *GetUsedSet();
 

	
 
@@ -216,13 +209,13 @@ public:
 
	 * @param md5sum whether to check the MD5 checksum
 
	 * @return true iff we have an set matching.
 
	 */
 
	static bool HasSet(const ContentInfo *ci, bool md5sum);
 
};
 

	
 
template <class Tbase_set> /* static */ const char *BaseMedia<Tbase_set>::ini_set;
 
template <class Tbase_set> /* static */ std::string BaseMedia<Tbase_set>::ini_set;
 
template <class Tbase_set> /* static */ const Tbase_set *BaseMedia<Tbase_set>::used_set;
 
template <class Tbase_set> /* static */ Tbase_set *BaseMedia<Tbase_set>::available_sets;
 
template <class Tbase_set> /* static */ Tbase_set *BaseMedia<Tbase_set>::duplicate_sets;
 

	
 
/**
 
 * Check whether there's a base set matching some information.
src/base_media_func.h
Show inline comments
 
@@ -39,22 +39,22 @@ template <class T, size_t Tnum_files, bo
 
bool BaseSet<T, Tnum_files, Tsearch_in_tars>::FillSetDetails(IniFile *ini, const char *path, const char *full_filename, bool allow_empty_filename)
 
{
 
	IniGroup *metadata = ini->GetGroup("metadata");
 
	IniItem *item;
 

	
 
	fetch_metadata("name");
 
	this->name = stredup(item->value->c_str());
 
	this->name = *item->value;
 

	
 
	fetch_metadata("description");
 
	this->description[stredup("")] = stredup(item->value->c_str());
 
	this->description[std::string{}] = *item->value;
 

	
 
	/* Add the translations of the descriptions too. */
 
	for (const IniItem *item = metadata->item; item != nullptr; item = item->next) {
 
		if (item->name.compare(0, 12, "description.") != 0) continue;
 

	
 
		this->description[stredup(item->name.c_str() + 12)] = stredup(item->value.value_or("").c_str());
 
		this->description[item->name.substr(12)] = item->value.value_or("");
 
	}
 

	
 
	fetch_metadata("shortname");
 
	for (uint i = 0; item->value.value()[i] != '\0' && i < 4; i++) {
 
		this->shortname |= ((uint8)item->value.value()[i]) << (i * 8);
 
	}
 
@@ -176,13 +176,13 @@ bool BaseMedia<Tbase_set>::AddFile(const
 
			}
 
		}
 
		if (duplicate != nullptr) {
 
			/* The more complete set takes precedence over the version number. */
 
			if ((duplicate->valid_files == set->valid_files && duplicate->version >= set->version) ||
 
					duplicate->valid_files > set->valid_files) {
 
				DEBUG(grf, 1, "Not adding %s (%i) as base " SET_TYPE " set (duplicate, %s)", set->name, set->version,
 
				DEBUG(grf, 1, "Not adding %s (%i) as base " SET_TYPE " set (duplicate, %s)", set->name.c_str(), set->version,
 
						duplicate->valid_files > set->valid_files ? "less valid files" : "lower version");
 
				set->next = BaseMedia<Tbase_set>::duplicate_sets;
 
				BaseMedia<Tbase_set>::duplicate_sets = set;
 
			} else {
 
				Tbase_set **prev = &BaseMedia<Tbase_set>::available_sets;
 
				while (*prev != duplicate) prev = &(*prev)->next;
 
@@ -192,13 +192,13 @@ bool BaseMedia<Tbase_set>::AddFile(const
 

	
 
				/* If the duplicate set is currently used (due to rescanning this can happen)
 
				 * update the currently used set to the new one. This will 'lie' about the
 
				 * version number until a new game is started which isn't a big problem */
 
				if (BaseMedia<Tbase_set>::used_set == duplicate) BaseMedia<Tbase_set>::used_set = set;
 

	
 
				DEBUG(grf, 1, "Removing %s (%i) as base " SET_TYPE " set (duplicate, %s)", duplicate->name, duplicate->version,
 
				DEBUG(grf, 1, "Removing %s (%i) as base " SET_TYPE " set (duplicate, %s)", duplicate->name.c_str(), duplicate->version,
 
						duplicate->valid_files < set->valid_files ? "less valid files" : "lower version");
 
				duplicate->next = BaseMedia<Tbase_set>::duplicate_sets;
 
				BaseMedia<Tbase_set>::duplicate_sets = duplicate;
 
				ret = true;
 
			}
 
		} else {
 
@@ -206,13 +206,13 @@ bool BaseMedia<Tbase_set>::AddFile(const
 
			while (*last != nullptr) last = &(*last)->next;
 

	
 
			*last = set;
 
			ret = true;
 
		}
 
		if (ret) {
 
			DEBUG(grf, 1, "Adding %s (%i) as base " SET_TYPE " set", set->name, set->version);
 
			DEBUG(grf, 1, "Adding %s (%i) as base " SET_TYPE " set", set->name.c_str(), set->version);
 
		}
 
	} else {
 
		delete set;
 
	}
 
	free(path);
 

	
 
@@ -223,24 +223,24 @@ bool BaseMedia<Tbase_set>::AddFile(const
 
/**
 
 * Set the set to be used.
 
 * @param name of the set to use
 
 * @return true if it could be loaded
 
 */
 
template <class Tbase_set>
 
/* static */ bool BaseMedia<Tbase_set>::SetSet(const char *name)
 
/* static */ bool BaseMedia<Tbase_set>::SetSet(const std::string &name)
 
{
 
	extern void CheckExternalFiles();
 

	
 
	if (StrEmpty(name)) {
 
	if (name.empty()) {
 
		if (!BaseMedia<Tbase_set>::DetermineBestSet()) return false;
 
		CheckExternalFiles();
 
		return true;
 
	}
 

	
 
	for (const Tbase_set *s = BaseMedia<Tbase_set>::available_sets; s != nullptr; s = s->next) {
 
		if (strcmp(name, s->name) == 0) {
 
		if (name == s->name) {
 
			BaseMedia<Tbase_set>::used_set = s;
 
			CheckExternalFiles();
 
			return true;
 
		}
 
	}
 
	return false;
 
@@ -254,13 +254,13 @@ template <class Tbase_set>
 
 */
 
template <class Tbase_set>
 
/* static */ char *BaseMedia<Tbase_set>::GetSetsList(char *p, const char *last)
 
{
 
	p += seprintf(p, last, "List of " SET_TYPE " sets:\n");
 
	for (const Tbase_set *s = BaseMedia<Tbase_set>::available_sets; s != nullptr; s = s->next) {
 
		p += seprintf(p, last, "%18s: %s", s->name, s->GetDescription());
 
		p += seprintf(p, last, "%18s: %s", s->name.c_str(), s->GetDescription({}));
 
		int invalid = s->GetNumInvalid();
 
		if (invalid != 0) {
 
			int missing = s->GetNumMissing();
 
			if (missing == 0) {
 
				p += seprintf(p, last, " (%i corrupt file%s)\n", invalid, invalid == 1 ? "" : "s");
 
			} else {
 
@@ -373,17 +373,17 @@ template <class Tbase_set>
 
/**
 
 * Force instantiation of methods so we don't get linker errors.
 
 * @param repl_type the type of the BaseMedia to instantiate
 
 * @param set_type  the type of the BaseSet to instantiate
 
 */
 
#define INSTANTIATE_BASE_MEDIA_METHODS(repl_type, set_type) \
 
	template const char *repl_type::ini_set; \
 
	template std::string repl_type::ini_set; \
 
	template const char *repl_type::GetExtension(); \
 
	template bool repl_type::AddFile(const char *filename, size_t pathlength, const char *tar_filename); \
 
	template bool repl_type::HasSet(const struct ContentInfo *ci, bool md5sum); \
 
	template bool repl_type::SetSet(const char *name); \
 
	template bool repl_type::SetSet(const std::string &name); \
 
	template char *repl_type::GetSetsList(char *p, const char *last); \
 
	template int repl_type::GetNumSets(); \
 
	template int repl_type::GetIndexOfUsedSet(); \
 
	template const set_type *repl_type::GetSet(int index); \
 
	template const set_type *repl_type::GetUsedSet(); \
 
	template bool repl_type::DetermineBestSet(); \
src/crashlog.cpp
Show inline comments
 
@@ -164,21 +164,21 @@ char *CrashLog::LogConfiguration(char *b
 
			" Music set:    %s (%u)\n"
 
			" Network:      %s\n"
 
			" Sound driver: %s\n"
 
			" Sound set:    %s (%u)\n"
 
			" Video driver: %s\n\n",
 
			BlitterFactory::GetCurrentBlitter() == nullptr ? "none" : BlitterFactory::GetCurrentBlitter()->GetName(),
 
			BaseGraphics::GetUsedSet() == nullptr ? "none" : BaseGraphics::GetUsedSet()->name,
 
			BaseGraphics::GetUsedSet() == nullptr ? "none" : BaseGraphics::GetUsedSet()->name.c_str(),
 
			BaseGraphics::GetUsedSet() == nullptr ? UINT32_MAX : BaseGraphics::GetUsedSet()->version,
 
			_current_language == nullptr ? "none" : _current_language->file,
 
			MusicDriver::GetInstance() == nullptr ? "none" : MusicDriver::GetInstance()->GetName(),
 
			BaseMusic::GetUsedSet() == nullptr ? "none" : BaseMusic::GetUsedSet()->name,
 
			BaseMusic::GetUsedSet() == nullptr ? "none" : BaseMusic::GetUsedSet()->name.c_str(),
 
			BaseMusic::GetUsedSet() == nullptr ? UINT32_MAX : BaseMusic::GetUsedSet()->version,
 
			_networking ? (_network_server ? "server" : "client") : "no",
 
			SoundDriver::GetInstance() == nullptr ? "none" : SoundDriver::GetInstance()->GetName(),
 
			BaseSounds::GetUsedSet() == nullptr ? "none" : BaseSounds::GetUsedSet()->name,
 
			BaseSounds::GetUsedSet() == nullptr ? "none" : BaseSounds::GetUsedSet()->name.c_str(),
 
			BaseSounds::GetUsedSet() == nullptr ? UINT32_MAX : BaseSounds::GetUsedSet()->version,
 
			VideoDriver::GetInstance() == nullptr ? "none" : VideoDriver::GetInstance()->GetName()
 
	);
 

	
 
	buffer += seprintf(buffer, last,
 
			"Fonts:\n"
src/gfxinit.cpp
Show inline comments
 
@@ -119,13 +119,13 @@ static void LoadGrfFileIndexed(const cha
 
void CheckExternalFiles()
 
{
 
	if (BaseGraphics::GetUsedSet() == nullptr || BaseSounds::GetUsedSet() == nullptr) return;
 

	
 
	const GraphicsSet *used_set = BaseGraphics::GetUsedSet();
 

	
 
	DEBUG(grf, 1, "Using the %s base graphics set", used_set->name);
 
	DEBUG(grf, 1, "Using the %s base graphics set", used_set->name.c_str());
 

	
 
	static const size_t ERROR_MESSAGE_LENGTH = 256;
 
	static const size_t MISSING_FILE_MESSAGE_LENGTH = 128;
 

	
 
	/* Allocate for a message for each missing file and for one error
 
	 * message per set.
 
@@ -134,23 +134,23 @@ void CheckExternalFiles()
 
	error_msg[0] = '\0';
 
	char *add_pos = error_msg;
 
	const char *last = lastof(error_msg);
 

	
 
	if (used_set->GetNumInvalid() != 0) {
 
		/* Not all files were loaded successfully, see which ones */
 
		add_pos += seprintf(add_pos, last, "Trying to load graphics set '%s', but it is incomplete. The game will probably not run correctly until you properly install this set or select another one. See section 4.1 of README.md.\n\nThe following files are corrupted or missing:\n", used_set->name);
 
		add_pos += seprintf(add_pos, last, "Trying to load graphics set '%s', but it is incomplete. The game will probably not run correctly until you properly install this set or select another one. See section 4.1 of README.md.\n\nThe following files are corrupted or missing:\n", used_set->name.c_str());
 
		for (uint i = 0; i < GraphicsSet::NUM_FILES; i++) {
 
			MD5File::ChecksumResult res = GraphicsSet::CheckMD5(&used_set->files[i], BASESET_DIR);
 
			if (res != MD5File::CR_MATCH) add_pos += seprintf(add_pos, last, "\t%s is %s (%s)\n", used_set->files[i].filename, res == MD5File::CR_MISMATCH ? "corrupt" : "missing", used_set->files[i].missing_warning);
 
		}
 
		add_pos += seprintf(add_pos, last, "\n");
 
	}
 

	
 
	const SoundsSet *sounds_set = BaseSounds::GetUsedSet();
 
	if (sounds_set->GetNumInvalid() != 0) {
 
		add_pos += seprintf(add_pos, last, "Trying to load sound set '%s', but it is incomplete. The game will probably not run correctly until you properly install this set or select another one. See section 4.1 of README.md.\n\nThe following files are corrupted or missing:\n", sounds_set->name);
 
		add_pos += seprintf(add_pos, last, "Trying to load sound set '%s', but it is incomplete. The game will probably not run correctly until you properly install this set or select another one. See section 4.1 of README.md.\n\nThe following files are corrupted or missing:\n", sounds_set->name.c_str());
 

	
 
		assert_compile(SoundsSet::NUM_FILES == 1);
 
		/* No need to loop each file, as long as there is only a single
 
		 * sound file. */
 
		add_pos += seprintf(add_pos, last, "\t%s is %s (%s)\n", sounds_set->files->filename, SoundsSet::CheckMD5(sounds_set->files, BASESET_DIR) == MD5File::CR_MISMATCH ? "corrupt" : "missing", sounds_set->files->missing_warning);
 
	}
src/music_gui.cpp
Show inline comments
 
@@ -62,13 +62,13 @@ struct MusicSystem {
 

	
 
	PlaylistChoices selected_playlist;
 

	
 
	void BuildPlaylists();
 

	
 
	void ChangePlaylist(PlaylistChoices pl);
 
	void ChangeMusicSet(const char *set_name);
 
	void ChangeMusicSet(const std::string &set_name);
 
	void Shuffle();
 
	void Unshuffle();
 

	
 
	void Play();
 
	void Stop();
 
	void Next();
 
@@ -164,18 +164,16 @@ void MusicSystem::ChangePlaylist(Playlis
 
}
 

	
 
/**
 
 * Change to named music set, and reset playback.
 
 * @param set_name Name of music set to select
 
 */
 
void MusicSystem::ChangeMusicSet(const char *set_name)
 
void MusicSystem::ChangeMusicSet(const std::string &set_name)
 
{
 
	BaseMusic::SetSet(set_name);
 

	
 
	free(BaseMusic::ini_set);
 
	BaseMusic::ini_set = stredup(set_name);
 
	BaseMusic::ini_set = set_name;
 

	
 
	this->BuildPlaylists();
 
	this->ChangePlaylist(this->selected_playlist);
 

	
 
	InvalidateWindowData(WC_GAME_OPTIONS, WN_GAME_OPTIONS_GAME_OPTIONS, 0, true);
 
}
 
@@ -430,14 +428,13 @@ void MusicLoop()
 
 * Change the configured music set and reset playback
 
 * @param index Index of music set to switch to
 
 */
 
void ChangeMusicSet(int index)
 
{
 
	if (BaseMusic::GetIndexOfUsedSet() == index) return;
 
	const char *name = BaseMusic::GetSet(index)->name;
 
	_music.ChangeMusicSet(name);
 
	_music.ChangeMusicSet(BaseMusic::GetSet(index)->name);
 
}
 

	
 
/**
 
 * Prepare the music system for use.
 
 * Called from \c InitializeGame
 
 */
 
@@ -461,13 +458,13 @@ struct MusicTrackSelectionWindow : publi
 
	{
 
		switch (widget) {
 
			case WID_MTS_PLAYLIST:
 
				SetDParam(0, STR_MUSIC_PLAYLIST_ALL + _settings_client.music.playlist);
 
				break;
 
			case WID_MTS_CAPTION:
 
				SetDParamStr(0, BaseMusic::GetUsedSet()->name);
 
				SetDParamStr(0, BaseMusic::GetUsedSet()->name.c_str());
 
				break;
 
		}
 
	}
 

	
 
	/**
 
	 * Some data on this window has become invalid.
src/newgrf_gui.cpp
Show inline comments
 
@@ -922,13 +922,13 @@ struct NewGRFWindow : public Window, New
 
				DropDownList list;
 

	
 
				/* Add 'None' option for clearing list */
 
				list.emplace_back(new DropDownListStringItem(STR_NONE, -1, false));
 

	
 
				for (uint i = 0; i < this->grf_presets.size(); i++) {
 
					list.emplace_back(new DropDownListCharStringItem(this->grf_presets[i].c_str(), i, false));
 
					list.emplace_back(new DropDownListCharStringItem(this->grf_presets[i], i, false));
 
				}
 

	
 
				this->DeleteChildWindows(WC_QUERY_STRING); // Remove the parameter query window
 
				ShowDropDownList(this, std::move(list), this->preset, WID_NS_PRESET_LIST);
 
				break;
 
			}
src/openttd.cpp
Show inline comments
 
@@ -534,15 +534,15 @@ static const OptionData _options[] = {
 
int openttd_main(int argc, char *argv[])
 
{
 
	char *musicdriver = nullptr;
 
	char *sounddriver = nullptr;
 
	char *videodriver = nullptr;
 
	char *blitter = nullptr;
 
	char *graphics_set = nullptr;
 
	char *sounds_set = nullptr;
 
	char *music_set = nullptr;
 
	std::string graphics_set;
 
	std::string sounds_set;
 
	std::string music_set;
 
	Dimension resolution = {0, 0};
 
	/* AfterNewGRFScan sets save_config to true after scanning completed. */
 
	bool save_config = false;
 
	AfterNewGRFScan *scanner = new AfterNewGRFScan(&save_config);
 
	bool dedicated = false;
 
	char *debuglog_conn = nullptr;
 
@@ -560,15 +560,15 @@ int openttd_main(int argc, char *argv[])
 
	GetOptData mgo(argc - 1, argv + 1, _options);
 
	int ret = 0;
 

	
 
	int i;
 
	while ((i = mgo.GetOpt()) != -1) {
 
		switch (i) {
 
		case 'I': free(graphics_set); graphics_set = stredup(mgo.opt); break;
 
		case 'S': free(sounds_set); sounds_set = stredup(mgo.opt); break;
 
		case 'M': free(music_set); music_set = stredup(mgo.opt); break;
 
		case 'I': graphics_set = mgo.opt; break;
 
		case 'S': sounds_set = mgo.opt; break;
 
		case 'M': music_set = mgo.opt; break;
 
		case 'm': free(musicdriver); musicdriver = stredup(mgo.opt); break;
 
		case 's': free(sounddriver); sounddriver = stredup(mgo.opt); break;
 
		case 'v': free(videodriver); videodriver = stredup(mgo.opt); break;
 
		case 'b': free(blitter); blitter = stredup(mgo.opt); break;
 
		case 'D':
 
			free(musicdriver);
 
@@ -728,23 +728,22 @@ int openttd_main(int argc, char *argv[])
 
	InitFreeType(false);
 

	
 
	/* This must be done early, since functions use the SetWindowDirty* calls */
 
	InitWindowSystem();
 

	
 
	BaseGraphics::FindSets();
 
	if (graphics_set == nullptr && BaseGraphics::ini_set != nullptr) graphics_set = stredup(BaseGraphics::ini_set);
 
	if (graphics_set.empty() && !BaseGraphics::ini_set.empty()) graphics_set = BaseGraphics::ini_set;
 
	if (!BaseGraphics::SetSet(graphics_set)) {
 
		if (!StrEmpty(graphics_set)) {
 
			BaseGraphics::SetSet(nullptr);
 
		if (!graphics_set.empty()) {
 
			BaseGraphics::SetSet({});
 

	
 
			ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_BASE_GRAPHICS_NOT_FOUND);
 
			msg.SetDParamStr(0, graphics_set);
 
			msg.SetDParamStr(0, graphics_set.c_str());
 
			ScheduleErrorMessage(msg);
 
		}
 
	}
 
	free(graphics_set);
 

	
 
	/* Initialize game palette */
 
	GfxInitPalettes();
 

	
 
	DEBUG(misc, 1, "Loading blitter...");
 
	if (blitter == nullptr && _ini_blitter != nullptr) blitter = stredup(_ini_blitter);
 
@@ -799,36 +798,34 @@ int openttd_main(int argc, char *argv[])
 
	VideoDriver::GetInstance()->ClaimMousePointer();
 

	
 
	/* initialize screenshot formats */
 
	InitializeScreenshotFormats();
 

	
 
	BaseSounds::FindSets();
 
	if (sounds_set == nullptr && BaseSounds::ini_set != nullptr) sounds_set = stredup(BaseSounds::ini_set);
 
	if (sounds_set.empty() && !BaseSounds::ini_set.empty()) sounds_set = BaseSounds::ini_set;
 
	if (!BaseSounds::SetSet(sounds_set)) {
 
		if (StrEmpty(sounds_set) || !BaseSounds::SetSet(nullptr)) {
 
		if (sounds_set.empty() || !BaseSounds::SetSet({})) {
 
			usererror("Failed to find a sounds set. Please acquire a sounds set for OpenTTD. See section 1.4 of README.md.");
 
		} else {
 
			ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_BASE_SOUNDS_NOT_FOUND);
 
			msg.SetDParamStr(0, sounds_set);
 
			msg.SetDParamStr(0, sounds_set.c_str());
 
			ScheduleErrorMessage(msg);
 
		}
 
	}
 
	free(sounds_set);
 

	
 
	BaseMusic::FindSets();
 
	if (music_set == nullptr && BaseMusic::ini_set != nullptr) music_set = stredup(BaseMusic::ini_set);
 
	if (music_set.empty() && !BaseMusic::ini_set.empty()) music_set = BaseMusic::ini_set;
 
	if (!BaseMusic::SetSet(music_set)) {
 
		if (StrEmpty(music_set) || !BaseMusic::SetSet(nullptr)) {
 
		if (music_set.empty() || !BaseMusic::SetSet({})) {
 
			usererror("Failed to find a music set. Please acquire a music set for OpenTTD. See section 1.4 of README.md.");
 
		} else {
 
			ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_INVALID_BASE_MUSIC_NOT_FOUND);
 
			msg.SetDParamStr(0, music_set);
 
			msg.SetDParamStr(0, music_set.c_str());
 
			ScheduleErrorMessage(msg);
 
		}
 
	}
 
	free(music_set);
 

	
 
	if (sounddriver == nullptr && _ini_sounddriver != nullptr) sounddriver = stredup(_ini_sounddriver);
 
	DriverFactoryBase::SelectDriver(sounddriver, Driver::DT_SOUND);
 
	free(sounddriver);
 

	
 
	if (musicdriver == nullptr && _ini_musicdriver != nullptr) musicdriver = stredup(_ini_musicdriver);
 
@@ -872,28 +869,21 @@ int openttd_main(int argc, char *argv[])
 
	/* Reset windowing system, stop drivers, free used memory, ... */
 
	ShutdownGame();
 
	goto exit_normal;
 

	
 
exit_noshutdown:
 
	/* These three are normally freed before bootstrap. */
 
	free(graphics_set);
 
	free(videodriver);
 
	free(blitter);
 

	
 
exit_bootstrap:
 
	/* These are normally freed before exit, but after bootstrap. */
 
	free(sounds_set);
 
	free(music_set);
 
	free(musicdriver);
 
	free(sounddriver);
 

	
 
exit_normal:
 
	free(BaseGraphics::ini_set);
 
	free(BaseSounds::ini_set);
 
	free(BaseMusic::ini_set);
 

	
 
	free(_ini_musicdriver);
 
	free(_ini_sounddriver);
 
	free(_ini_videodriver);
 
	free(_ini_blitter);
 

	
 
	delete scanner;
 
@@ -1139,15 +1129,15 @@ void SwitchToMode(SwitchMode new_mode)
 
			}
 
			break;
 
		}
 

	
 
		case SM_MENU: // Switch to game intro menu
 
			LoadIntroGame();
 
			if (BaseSounds::ini_set == nullptr && BaseSounds::GetUsedSet()->fallback) {
 
			if (BaseSounds::ini_set.empty() && BaseSounds::GetUsedSet()->fallback) {
 
				ShowErrorMessage(STR_WARNING_FALLBACK_SOUNDSET, INVALID_STRING_ID, WL_CRITICAL);
 
				BaseSounds::ini_set = stredup(BaseSounds::GetUsedSet()->name);
 
				BaseSounds::ini_set = BaseSounds::GetUsedSet()->name;
 
			}
 
			break;
 

	
 
		case SM_SAVE_GAME: // Save game.
 
			/* Make network saved games on pause compatible to singleplayer */
 
			if (SaveOrLoad(_file_to_saveload.name, SLO_SAVE, DFT_GAME_FILE, NO_DIRECTORY) != SL_OK) {
src/screenshot.cpp
Show inline comments
 
@@ -307,13 +307,13 @@ static bool MakePNGImage(const char *nam
 
	text[0].text = const_cast<char *>(_openttd_revision);
 
	text[0].text_length = strlen(_openttd_revision);
 
	text[0].compression = PNG_TEXT_COMPRESSION_NONE;
 

	
 
	char buf[8192];
 
	char *p = buf;
 
	p += seprintf(p, lastof(buf), "Graphics set: %s (%u)\n", BaseGraphics::GetUsedSet()->name, BaseGraphics::GetUsedSet()->version);
 
	p += seprintf(p, lastof(buf), "Graphics set: %s (%u)\n", BaseGraphics::GetUsedSet()->name.c_str(), BaseGraphics::GetUsedSet()->version);
 
	p = strecpy(p, "NewGRFs:\n", lastof(buf));
 
	for (const GRFConfig *c = _game_mode == GM_MENU ? nullptr : _grfconfig; c != nullptr; c = c->next) {
 
		p += seprintf(p, lastof(buf), "%08X ", BSWAP32(c->ident.grfid));
 
		p = md5sumToString(p, lastof(buf), c->ident.md5sum);
 
		p += seprintf(p, lastof(buf), " %s\n", c->filename);
 
	}
src/settings.cpp
Show inline comments
 
@@ -411,12 +411,13 @@ static const void *StringToVal(const Set
 
			msg.SetDParamStr(0, str);
 
			msg.SetDParamStr(1, desc->name);
 
			_settings_error_list.push_back(msg);
 
			return desc->def;
 
		}
 

	
 
		case SDT_STDSTRING:
 
		case SDT_STRING: return orig_str;
 
		case SDT_INTLIST: return str;
 
		default: break;
 
	}
 

	
 
	return nullptr;
 
@@ -562,12 +563,28 @@ static void IniLoadSettings(IniFile *ini
 
					case SLE_VAR_CHAR: if (p != nullptr) *(char *)ptr = *(const char *)p; break;
 

	
 
					default: NOT_REACHED();
 
				}
 
				break;
 

	
 
			case SDT_STDSTRING:
 
				switch (GetVarMemType(sld->conv)) {
 
					case SLE_VAR_STR:
 
					case SLE_VAR_STRQ:
 
						if (p != nullptr) {
 
							reinterpret_cast<std::string *>(ptr)->assign((const char *)p);
 
						} else {
 
							reinterpret_cast<std::string *>(ptr)->clear();
 
						}
 
						break;
 

	
 
					default: NOT_REACHED();
 
				}
 

	
 
				break;
 

	
 
			case SDT_INTLIST: {
 
				if (!LoadIntList((const char*)p, ptr, sld->length, GetVarMemType(sld->conv))) {
 
					ErrorMessageData msg(STR_CONFIG_ERROR, STR_CONFIG_ERROR_ARRAY);
 
					msg.SetDParamStr(0, sdb->name);
 
					_settings_error_list.push_back(msg);
 

	
 
@@ -698,12 +715,28 @@ static void IniSaveSettings(IniFile *ini
 

	
 
					case SLE_VAR_CHAR: buf[0] = *(char*)ptr; buf[1] = '\0'; break;
 
					default: NOT_REACHED();
 
				}
 
				break;
 

	
 
			case SDT_STDSTRING:
 
				switch (GetVarMemType(sld->conv)) {
 
					case SLE_VAR_STR: strecpy(buf, reinterpret_cast<std::string *>(ptr)->c_str(), lastof(buf)); break;
 

	
 
					case SLE_VAR_STRQ:
 
						if (reinterpret_cast<std::string *>(ptr)->empty()) {
 
							buf[0] = '\0';
 
						} else {
 
							seprintf(buf, lastof(buf), "\"%s\"", reinterpret_cast<std::string *>(ptr)->c_str());
 
						}
 
						break;
 

	
 
					default: NOT_REACHED();
 
				}
 
				break;
 

	
 
			case SDT_INTLIST:
 
				MakeIntList(buf, lastof(buf), ptr, sld->length, sld->conv);
 
				break;
 

	
 
			default: NOT_REACHED();
 
		}
src/settings_gui.cpp
Show inline comments
 
@@ -149,13 +149,13 @@ struct BaseSetTextfileWindow : public Te
 
	}
 

	
 
	void SetStringParameters(int widget) const override
 
	{
 
		if (widget == WID_TF_CAPTION) {
 
			SetDParam(0, content_type);
 
			SetDParamStr(1, this->baseset->name);
 
			SetDParamStr(1, this->baseset->name.c_str());
 
		}
 
	}
 
};
 

	
 
/**
 
 * Open the BaseSet version of the textfile window.
 
@@ -332,16 +332,16 @@ struct GameOptionsWindow : Window {
 
			case WID_GO_TOWNNAME_DROPDOWN:   SetDParam(0, TownName(this->opt->game_creation.town_name)); break;
 
			case WID_GO_AUTOSAVE_DROPDOWN:   SetDParam(0, _autosave_dropdown[_settings_client.gui.autosave]); break;
 
			case WID_GO_LANG_DROPDOWN:       SetDParamStr(0, _current_language->own_name); break;
 
			case WID_GO_RESOLUTION_DROPDOWN: SetDParam(0, GetCurRes() == _resolutions.size() ? STR_GAME_OPTIONS_RESOLUTION_OTHER : SPECSTR_RESOLUTION_START + GetCurRes()); break;
 
			case WID_GO_GUI_ZOOM_DROPDOWN:   SetDParam(0, _gui_zoom_dropdown[ZOOM_LVL_OUT_4X - _gui_zoom]); break;
 
			case WID_GO_FONT_ZOOM_DROPDOWN:  SetDParam(0, _font_zoom_dropdown[ZOOM_LVL_OUT_4X - _font_zoom]); break;
 
			case WID_GO_BASE_GRF_DROPDOWN:   SetDParamStr(0, BaseGraphics::GetUsedSet()->name); break;
 
			case WID_GO_BASE_GRF_DROPDOWN:   SetDParamStr(0, BaseGraphics::GetUsedSet()->name.c_str()); break;
 
			case WID_GO_BASE_GRF_STATUS:     SetDParam(0, BaseGraphics::GetUsedSet()->GetNumInvalid()); break;
 
			case WID_GO_BASE_SFX_DROPDOWN:   SetDParamStr(0, BaseSounds::GetUsedSet()->name); break;
 
			case WID_GO_BASE_MUSIC_DROPDOWN: SetDParamStr(0, BaseMusic::GetUsedSet()->name); break;
 
			case WID_GO_BASE_SFX_DROPDOWN:   SetDParamStr(0, BaseSounds::GetUsedSet()->name.c_str()); break;
 
			case WID_GO_BASE_MUSIC_DROPDOWN: SetDParamStr(0, BaseMusic::GetUsedSet()->name.c_str()); break;
 
			case WID_GO_BASE_MUSIC_STATUS:   SetDParam(0, BaseMusic::GetUsedSet()->GetNumInvalid()); break;
 
		}
 
	}
 

	
 
	void DrawWidget(const Rect &r, int widget) const override
 
	{
 
@@ -478,16 +478,15 @@ struct GameOptionsWindow : Window {
 
	 * @tparam T class of media set
 
	 */
 
	template <class T>
 
	void SetMediaSet(int index)
 
	{
 
		if (_game_mode == GM_MENU) {
 
			const char *name = T::GetSet(index)->name;
 
			auto name = T::GetSet(index)->name;
 

	
 
			free(T::ini_set);
 
			T::ini_set = stredup(name);
 
			T::ini_set = name;
 

	
 
			T::SetSet(name);
 
			this->reload = true;
 
			this->InvalidateData();
 
		}
 
	}
src/settings_internal.h
Show inline comments
 
@@ -24,14 +24,15 @@ enum SettingDescType : byte {
 
	SDT_NUMX        = 0, ///< any number-type
 
	SDT_BOOLX       = 1, ///< a boolean number
 
	SDT_ONEOFMANY   = 2, ///< bitmasked number where only ONE bit may be set
 
	SDT_MANYOFMANY  = 3, ///< bitmasked number where MULTIPLE bits may be set
 
	SDT_INTLIST     = 4, ///< list of integers separated by a comma ','
 
	SDT_STRING      = 5, ///< string with a pre-allocated buffer
 
	SDT_STDSTRING   = 6, ///< \c std::string
 
	SDT_END,
 
	/* 10 more possible primitives */
 
	/* 9 more possible primitives */
 
};
 

	
 

	
 
enum SettingGuiFlag : uint16 {
 
	/* 1 byte allocated for a maximum of 8 flags
 
	 * Flags directing saving/loading of a variable */
src/table/misc_settings.ini
Show inline comments
 
@@ -14,12 +14,13 @@ static const SettingDescGlobVarList _mis
 
};
 
[templates]
 
SDTG_LIST  =  SDTG_LIST($name, $type, $length, $flags, $guiflags, $var, $def,                               $str, $strhelp, $strval, $proc, $from, $to, $cat),
 
SDTG_MMANY = SDTG_MMANY($name, $type,          $flags, $guiflags, $var, $def,                        $full, $str, $strhelp, $strval, $proc, $from, $to, $cat),
 
SDTG_OMANY = SDTG_OMANY($name, $type,          $flags, $guiflags, $var, $def,       $max,            $full, $str, $strhelp, $strval, $proc, $from, $to, $cat),
 
SDTG_STR   =   SDTG_STR($name, $type,          $flags, $guiflags, $var, $def,                               $str, $strhelp, $strval, $proc, $from, $to, $cat),
 
SDTG_SSTR  =  SDTG_SSTR($name, $type,          $flags, $guiflags, $var, $def,                               $str, $strhelp, $strval, $proc, $from, $to, $cat),
 
SDTG_BOOL  =  SDTG_BOOL($name,                 $flags, $guiflags, $var, $def,                               $str, $strhelp, $strval, $proc, $from, $to, $cat),
 
SDTG_VAR   =   SDTG_VAR($name, $type,          $flags, $guiflags, $var, $def, $min, $max, $interval,        $str, $strhelp, $strval, $proc, $from, $to, $cat),
 
SDTG_END   = SDTG_END()
 

	
 
[defaults]
 
flags    = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
 
@@ -55,27 +56,27 @@ type     = SLE_UINT8
 
var      = _support8bpp
 
def      = 0
 
max      = 2
 
full     = _support8bppmodes
 
cat      = SC_BASIC
 

	
 
[SDTG_STR]
 
[SDTG_SSTR]
 
name     = ""graphicsset""
 
type     = SLE_STRQ
 
var      = BaseGraphics::ini_set
 
def      = nullptr
 
cat      = SC_BASIC
 

	
 
[SDTG_STR]
 
[SDTG_SSTR]
 
name     = ""soundsset""
 
type     = SLE_STRQ
 
var      = BaseSounds::ini_set
 
def      = nullptr
 
cat      = SC_BASIC
 

	
 
[SDTG_STR]
 
[SDTG_SSTR]
 
name     = ""musicset""
 
type     = SLE_STRQ
 
var      = BaseMusic::ini_set
 
def      = nullptr
 
cat      = SC_BASIC
 

	
src/table/settings.h.preamble
Show inline comments
 
@@ -71,12 +71,15 @@ static size_t ConvertLandscape(const cha
 
#define SDTG_LIST(name, type, length, flags, guiflags, var, def, str, strhelp, strval, proc, from, to, cat)\
 
	SDTG_GENERAL(name, SDT_INTLIST, SL_ARR, type, flags, guiflags, var, length, def, 0, 0, 0, nullptr, str, strhelp, strval, proc, from, to, cat)
 

	
 
#define SDTG_STR(name, type, flags, guiflags, var, def, str, strhelp, strval, proc, from, to, cat)\
 
	SDTG_GENERAL(name, SDT_STRING, SL_STR, type, flags, guiflags, var, sizeof(var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, from, to, cat)
 

	
 
#define SDTG_SSTR(name, type, flags, guiflags, var, def, str, strhelp, strval, proc, from, to, cat)\
 
    SDTG_GENERAL(name, SDT_STDSTRING, SL_STDSTR, type, flags, guiflags, var, sizeof(var), def, 0, 0, 0, nullptr, str, strhelp, strval, proc, from, to, cat)
 

	
 
#define SDTG_OMANY(name, type, flags, guiflags, var, def, max, full, str, strhelp, strval, proc, from, to, cat)\
 
	SDTG_GENERAL(name, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, var, 0, def, 0, max, 0, full, str, strhelp, strval, proc, from, to, cat)
 

	
 
#define SDTG_MMANY(name, type, flags, guiflags, var, def, full, str, strhelp, strval, proc, from, to, cat)\
 
	SDTG_GENERAL(name, SDT_MANYOFMANY, SL_VAR, type, flags, guiflags, var, 0, def, 0, 0, 0, full, str, strhelp, strval, proc, from, to, cat)
 

	
src/widgets/dropdown.cpp
Show inline comments
 
@@ -62,13 +62,13 @@ StringID DropDownListParamStringItem::St
 
	for (uint i = 0; i < lengthof(this->decode_params); i++) SetDParam(i, this->decode_params[i]);
 
	return this->string;
 
}
 

	
 
StringID DropDownListCharStringItem::String() const
 
{
 
	SetDParamStr(0, this->raw_string);
 
	SetDParamStr(0, this->raw_string.c_str());
 
	return this->string;
 
}
 

	
 
DropDownListIconItem::DropDownListIconItem(SpriteID sprite, PaletteID pal, StringID string, int result, bool masked) : DropDownListParamStringItem(string, result, masked), sprite(sprite), pal(pal)
 
{
 
	this->dim = GetSpriteSize(sprite);
src/widgets/dropdown_type.h
Show inline comments
 
@@ -65,15 +65,15 @@ public:
 

	
 
/**
 
 * List item containing a C char string.
 
 */
 
class DropDownListCharStringItem : public DropDownListStringItem {
 
public:
 
	const char *raw_string;
 
	std::string raw_string;
 

	
 
	DropDownListCharStringItem(const char *raw_string, int result, bool masked) : DropDownListStringItem(STR_JUST_RAW_STRING, result, masked), raw_string(raw_string) {}
 
	DropDownListCharStringItem(const std::string &raw_string, int result, bool masked) : DropDownListStringItem(STR_JUST_RAW_STRING, result, masked), raw_string(raw_string) {}
 

	
 
	StringID String() const override;
 
};
 

	
 
/**
 
 * List item with icon and string.
0 comments (0 inline, 0 general)