Changeset - r24209:155ba259d4af
[Not reviewed]
master
0 7 0
Michael Lutz - 4 years ago 2020-05-17 21:31:47
michi@icosahedron.de
Codechange: Replace custom linked list for GRF texts with STL vectors and strings.
7 files changed with 131 insertions and 261 deletions:
0 comments (0 inline, 0 general)
src/network/network_gamelist.cpp
Show inline comments
 
@@ -175,21 +175,15 @@ void NetworkAfterNewGRFScan()
 
				/* Don't know the GRF, so mark game incompatible and the (possibly)
 
				 * already resolved name for this GRF (another server has sent the
 
				 * name of the GRF already. */
 
				c->name->Release();
 
				c->name = FindUnknownGRFName(c->ident.grfid, c->ident.md5sum, true);
 
				c->name->AddRef();
 
				c->status = GCS_NOT_FOUND;
 

	
 
				/* If we miss a file, we're obviously incompatible. */
 
				item->info.compatible = false;
 
			} else {
 
				c->filename = f->filename;
 
				c->name->Release();
 
				c->name = f->name;
 
				c->name->AddRef();
 
				c->info->Release();
 
				c->info = f->info;
 
				c->info->AddRef();
 
				c->status = GCS_UNKNOWN;
 
			}
 
		}
src/network/network_udp.cpp
Show inline comments
 
@@ -426,9 +426,9 @@ void ClientNetworkUDPSocketHandler::Rece
 
		/* Try to find the GRFTextWrapper for the name of this GRF ID and MD5sum tuple.
 
		 * If it exists and not resolved yet, then name of the fake GRF is
 
		 * overwritten with the name from the reply. */
 
		GRFTextWrapper *unknown_name = FindUnknownGRFName(c.grfid, c.md5sum, false);
 
		if (unknown_name != nullptr && strcmp(GetGRFStringFromGRFText(unknown_name->text), UNKNOWN_GRF_NAME_PLACEHOLDER) == 0) {
 
			AddGRFTextToList(&unknown_name->text, name);
 
		GRFTextWrapper unknown_name = FindUnknownGRFName(c.grfid, c.md5sum, false);
 
		if (unknown_name && strcmp(GetGRFStringFromGRFText(unknown_name), UNKNOWN_GRF_NAME_PLACEHOLDER) == 0) {
 
			AddGRFTextToList(unknown_name, name);
 
		}
 
	}
 
}
 
@@ -441,21 +441,13 @@ void ClientNetworkUDPSocketHandler::Hand
 
		/* Don't know the GRF, so mark game incompatible and the (possibly)
 
		 * already resolved name for this GRF (another server has sent the
 
		 * name of the GRF already */
 
		config->name->Release();
 
		config->name = FindUnknownGRFName(config->ident.grfid, config->ident.md5sum, true);
 
		config->name->AddRef();
 
		config->status = GCS_NOT_FOUND;
 
	} else {
 
		config->filename = f->filename;
 
		config->name->Release();
 
		config->name = f->name;
 
		config->name->AddRef();
 
		config->info->Release();
 
		config->info = f->info;
 
		config->info->AddRef();
 
		config->url->Release();
 
		config->url = f->url;
 
		config->url->AddRef();
 
	}
 
	SetBit(config->flags, GCF_COPY);
 
}
src/newgrf.cpp
Show inline comments
 
@@ -6720,11 +6720,11 @@ static void ScanInfo(ByteReader *buf)
 
	/* GRF IDs starting with 0xFF are reserved for internal TTDPatch use */
 
	if (GB(grfid, 0, 8) == 0xFF) SetBit(_cur.grfconfig->flags, GCF_SYSTEM);
 

	
 
	AddGRFTextToList(&_cur.grfconfig->name->text, 0x7F, grfid, false, name);
 
	AddGRFTextToList(_cur.grfconfig->name, 0x7F, grfid, false, name);
 

	
 
	if (buf->HasData()) {
 
		const char *info = buf->ReadString();
 
		AddGRFTextToList(&_cur.grfconfig->info->text, 0x7F, grfid, true, info);
 
		AddGRFTextToList(_cur.grfconfig->info, 0x7F, grfid, true, info);
 
	}
 

	
 
	/* GLS_INFOSCAN only looks for the action 8, so we can skip the rest of the file */
 
@@ -7806,21 +7806,21 @@ static void TranslateGRFStrings(ByteRead
 
/** Callback function for 'INFO'->'NAME' to add a translation to the newgrf name. */
 
static bool ChangeGRFName(byte langid, const char *str)
 
{
 
	AddGRFTextToList(&_cur.grfconfig->name->text, langid, _cur.grfconfig->ident.grfid, false, str);
 
	AddGRFTextToList(_cur.grfconfig->name, langid, _cur.grfconfig->ident.grfid, false, str);
 
	return true;
 
}
 

	
 
/** Callback function for 'INFO'->'DESC' to add a translation to the newgrf description. */
 
static bool ChangeGRFDescription(byte langid, const char *str)
 
{
 
	AddGRFTextToList(&_cur.grfconfig->info->text, langid, _cur.grfconfig->ident.grfid, true, str);
 
	AddGRFTextToList(_cur.grfconfig->info, langid, _cur.grfconfig->ident.grfid, true, str);
 
	return true;
 
}
 

	
 
/** Callback function for 'INFO'->'URL_' to set the newgrf url. */
 
static bool ChangeGRFURL(byte langid, const char *str)
 
{
 
	AddGRFTextToList(&_cur.grfconfig->url->text, langid, _cur.grfconfig->ident.grfid, false, str);
 
	AddGRFTextToList(_cur.grfconfig->url, langid, _cur.grfconfig->ident.grfid, false, str);
 
	return true;
 
}
 

	
 
@@ -7922,14 +7922,14 @@ static GRFParameterInfo *_cur_parameter;
 
/** Callback function for 'INFO'->'PARAM'->param_num->'NAME' to set the name of a parameter. */
 
static bool ChangeGRFParamName(byte langid, const char *str)
 
{
 
	AddGRFTextToList(&_cur_parameter->name, langid, _cur.grfconfig->ident.grfid, false, str);
 
	AddGRFTextToList(_cur_parameter->name, langid, _cur.grfconfig->ident.grfid, false, str);
 
	return true;
 
}
 

	
 
/** Callback function for 'INFO'->'PARAM'->param_num->'DESC' to set the description of a parameter. */
 
static bool ChangeGRFParamDescription(byte langid, const char *str)
 
{
 
	AddGRFTextToList(&_cur_parameter->desc, langid, _cur.grfconfig->ident.grfid, true, str);
 
	AddGRFTextToList(_cur_parameter->desc, langid, _cur.grfconfig->ident.grfid, true, str);
 
	return true;
 
}
 

	
 
@@ -8113,12 +8113,12 @@ static bool ChangeGRFParamValueNames(Byt
 
		byte langid = buf->ReadByte();
 
		const char *name_string = buf->ReadString();
 

	
 
		std::pair<uint32, GRFText *> *val_name = _cur_parameter->value_names.Find(id);
 
		std::pair<uint32, GRFTextList> *val_name = _cur_parameter->value_names.Find(id);
 
		if (val_name != _cur_parameter->value_names.End()) {
 
			AddGRFTextToList(&val_name->second, langid, _cur.grfconfig->ident.grfid, false, name_string);
 
			AddGRFTextToList(val_name->second, langid, _cur.grfconfig->ident.grfid, false, name_string);
 
		} else {
 
			GRFText *list = nullptr;
 
			AddGRFTextToList(&list, langid, _cur.grfconfig->ident.grfid, false, name_string);
 
			GRFTextList list;
 
			AddGRFTextToList(list, langid, _cur.grfconfig->ident.grfid, false, name_string);
 
			_cur_parameter->value_names.Insert(id, list);
 
		}
 

	
src/newgrf_config.cpp
Show inline comments
 
@@ -21,23 +21,13 @@
 
#include "textfile_gui.h"
 
#include "thread.h"
 
#include "newgrf_config.h"
 
#include "newgrf_text.h"
 

	
 
#include "fileio_func.h"
 
#include "fios.h"
 

	
 
#include "safeguards.h"
 

	
 
/** Create a new GRFTextWrapper. */
 
GRFTextWrapper::GRFTextWrapper() :
 
	text(nullptr)
 
{
 
}
 

	
 
/** Cleanup a GRFTextWrapper object. */
 
GRFTextWrapper::~GRFTextWrapper()
 
{
 
	CleanUpGRFText(this->text);
 
}
 

	
 
/**
 
 * Create a new GRFConfig.
 
@@ -45,15 +35,9 @@ GRFTextWrapper::~GRFTextWrapper()
 
 *   is copied so the original string isn't needed after the constructor.
 
 */
 
GRFConfig::GRFConfig(const char *filename) :
 
	name(new GRFTextWrapper()),
 
	info(new GRFTextWrapper()),
 
	url(new GRFTextWrapper()),
 
	num_valid_params(lengthof(param))
 
{
 
	if (filename != nullptr) this->filename = stredup(filename);
 
	this->name->AddRef();
 
	this->info->AddRef();
 
	this->url->AddRef();
 
}
 

	
 
/**
 
@@ -79,9 +63,6 @@ GRFConfig::GRFConfig(const GRFConfig &co
 
	MemCpyT<uint8>(this->original_md5sum, config.original_md5sum, lengthof(this->original_md5sum));
 
	MemCpyT<uint32>(this->param, config.param, lengthof(this->param));
 
	if (config.filename != nullptr) this->filename = stredup(config.filename);
 
	this->name->AddRef();
 
	this->info->AddRef();
 
	this->url->AddRef();
 
	if (config.error != nullptr) this->error = new GRFError(*config.error);
 
	for (uint i = 0; i < config.param_info.size(); i++) {
 
		if (config.param_info[i] == nullptr) {
 
@@ -100,9 +81,6 @@ GRFConfig::~GRFConfig()
 
		free(this->filename);
 
		delete this->error;
 
	}
 
	this->name->Release();
 
	this->info->Release();
 
	this->url->Release();
 

	
 
	for (uint i = 0; i < this->param_info.size(); i++) delete this->param_info[i];
 
}
 
@@ -125,7 +103,7 @@ void GRFConfig::CopyParams(const GRFConf
 
 */
 
const char *GRFConfig::GetName() const
 
{
 
	const char *name = GetGRFStringFromGRFText(this->name->text);
 
	const char *name = GetGRFStringFromGRFText(this->name);
 
	return StrEmpty(name) ? this->filename : name;
 
}
 

	
 
@@ -135,7 +113,7 @@ const char *GRFConfig::GetName() const
 
 */
 
const char *GRFConfig::GetDescription() const
 
{
 
	return GetGRFStringFromGRFText(this->info->text);
 
	return GetGRFStringFromGRFText(this->info);
 
}
 

	
 
/**
 
@@ -144,7 +122,7 @@ const char *GRFConfig::GetDescription() 
 
 */
 
const char *GRFConfig::GetURL() const
 
{
 
	return GetGRFStringFromGRFText(this->url->text);
 
	return GetGRFStringFromGRFText(this->url);
 
}
 

	
 
/** Set the default value for all parameters as specified by action14. */
 
@@ -232,8 +210,8 @@ GRFError::~GRFError()
 
 * @param nr The newgrf parameter that is changed.
 
 */
 
GRFParameterInfo::GRFParameterInfo(uint nr) :
 
	name(nullptr),
 
	desc(nullptr),
 
	name(),
 
	desc(),
 
	type(PTYPE_UINT_ENUM),
 
	min_value(0),
 
	max_value(UINT32_MAX),
 
@@ -241,6 +219,7 @@ GRFParameterInfo::GRFParameterInfo(uint 
 
	param_nr(nr),
 
	first_bit(0),
 
	num_bit(32),
 
	value_names(),
 
	complete_labels(false)
 
{}
 

	
 
@@ -250,8 +229,8 @@ GRFParameterInfo::GRFParameterInfo(uint 
 
 * @param info The GRFParameterInfo object to make a copy of.
 
 */
 
GRFParameterInfo::GRFParameterInfo(GRFParameterInfo &info) :
 
	name(DuplicateGRFText(info.name)),
 
	desc(DuplicateGRFText(info.desc)),
 
	name(info.name),
 
	desc(info.desc),
 
	type(info.type),
 
	min_value(info.min_value),
 
	max_value(info.max_value),
 
@@ -259,23 +238,9 @@ GRFParameterInfo::GRFParameterInfo(GRFPa
 
	param_nr(info.param_nr),
 
	first_bit(info.first_bit),
 
	num_bit(info.num_bit),
 
	value_names(info.value_names),
 
	complete_labels(info.complete_labels)
 
{
 
	for (uint i = 0; i < info.value_names.size(); i++) {
 
		std::pair<uint32, GRFText *> *data = info.value_names.data() + i;
 
		this->value_names.Insert(data->first, DuplicateGRFText(data->second));
 
	}
 
}
 

	
 
/** Cleanup all parameter info. */
 
GRFParameterInfo::~GRFParameterInfo()
 
{
 
	CleanUpGRFText(this->name);
 
	CleanUpGRFText(this->desc);
 
	for (uint i = 0; i < this->value_names.size(); i++) {
 
		std::pair<uint32, GRFText *> *data = this->value_names.data() + i;
 
		CleanUpGRFText(data->second);
 
	}
 
}
 

	
 
/**
 
@@ -598,12 +563,8 @@ compatible_grf:
 
				free(c->filename);
 
				c->filename = stredup(f->filename);
 
				memcpy(c->ident.md5sum, f->ident.md5sum, sizeof(c->ident.md5sum));
 
				c->name->Release();
 
				c->name = f->name;
 
				c->name->AddRef();
 
				c->info->Release();
 
				c->info = f->name;
 
				c->info->AddRef();
 
				c->error = nullptr;
 
				c->version = f->version;
 
				c->min_loadable_version = f->min_loadable_version;
 
@@ -686,7 +647,7 @@ bool GRFFileScanner::AddFile(const char 
 
		_modal_progress_paint_mutex.lock();
 

	
 
		const char *name = nullptr;
 
		if (c->name != nullptr) name = GetGRFStringFromGRFText(c->name->text);
 
		if (c->name != nullptr) name = GetGRFStringFromGRFText(c->name);
 
		if (name == nullptr) name = c->filename;
 
		UpdateNewGRFScanStatus(this->num_scanned, name);
 

	
 
@@ -820,8 +781,12 @@ const GRFConfig *FindGRFConfig(uint32 gr
 

	
 
/** Structure for UnknownGRFs; this is a lightweight variant of GRFConfig */
 
struct UnknownGRF : public GRFIdentifier {
 
	UnknownGRF *next;     ///< The next unknown GRF.
 
	GRFTextWrapper *name; ///< Name of the GRF.
 
	GRFTextWrapper name; ///< Name of the GRF.
 

	
 
	UnknownGRF() = default;
 
	UnknownGRF(const UnknownGRF &other) = default;
 
	UnknownGRF(UnknownGRF &&other) = default;
 
	UnknownGRF(uint32 grfid, const uint8 *_md5sum) : GRFIdentifier(grfid, _md5sum), name(new GRFTextList) {}
 
};
 

	
 
/**
 
@@ -841,30 +806,24 @@ struct UnknownGRF : public GRFIdentifier
 
 *         and MD5 checksum or nullptr when it does not exist and create is false.
 
 *         This value must NEVER be freed by the caller.
 
 */
 
GRFTextWrapper *FindUnknownGRFName(uint32 grfid, uint8 *md5sum, bool create)
 
GRFTextWrapper FindUnknownGRFName(uint32 grfid, uint8 *md5sum, bool create)
 
{
 
	UnknownGRF *grf;
 
	static UnknownGRF *unknown_grfs = nullptr;
 
	static std::vector<UnknownGRF> unknown_grfs;
 

	
 
	for (grf = unknown_grfs; grf != nullptr; grf = grf->next) {
 
		if (grf->grfid == grfid) {
 
			if (memcmp(md5sum, grf->md5sum, sizeof(grf->md5sum)) == 0) return grf->name;
 
	for (const auto &grf : unknown_grfs) {
 
		if (grf.grfid == grfid) {
 
			if (memcmp(md5sum, grf.md5sum, sizeof(grf.md5sum)) == 0) return grf.name;
 
		}
 
	}
 

	
 
	if (!create) return nullptr;
 

	
 
	grf = CallocT<UnknownGRF>(1);
 
	grf->grfid = grfid;
 
	grf->next  = unknown_grfs;
 
	grf->name = new GRFTextWrapper();
 
	grf->name->AddRef();
 
	unknown_grfs.emplace_back(grfid, md5sum);
 
	UnknownGRF &grf = unknown_grfs.back();
 

	
 
	AddGRFTextToList(&grf->name->text, UNKNOWN_GRF_NAME_PLACEHOLDER);
 
	memcpy(grf->md5sum, md5sum, sizeof(grf->md5sum));
 
	AddGRFTextToList(grf.name, UNKNOWN_GRF_NAME_PLACEHOLDER);
 

	
 
	unknown_grfs = grf;
 
	return grf->name;
 
	return grf.name;
 
}
 

	
 
/**
src/newgrf_config.h
Show inline comments
 
@@ -16,6 +16,7 @@
 
#include "misc/countedptr.hpp"
 
#include "fileio_type.h"
 
#include "textfile_type.h"
 
#include "newgrf_text.h"
 

	
 
/** GRF config bit flags */
 
enum GCF_Flags {
 
@@ -83,6 +84,16 @@ struct GRFIdentifier {
 
	uint32 grfid;     ///< GRF ID (defined by Action 0x08)
 
	uint8 md5sum[16]; ///< MD5 checksum of file to distinguish files with the same GRF ID (eg. newer version of GRF)
 

	
 
	GRFIdentifier() = default;
 
	GRFIdentifier(const GRFIdentifier &other) = default;
 
	GRFIdentifier(GRFIdentifier &&other) = default;
 
	GRFIdentifier(uint32 grfid, const uint8 *md5sum) : grfid(grfid)
 
	{
 
		MemCpyT(this->md5sum, md5sum, lengthof(this->md5sum));
 
	}
 

	
 
	GRFIdentifier& operator =(const GRFIdentifier &other) = default;
 

	
 
	/**
 
	 * Does the identification match the provided values?
 
	 * @param grfid  Expected grfid.
 
@@ -121,9 +132,8 @@ enum GRFParameterType {
 
struct GRFParameterInfo {
 
	GRFParameterInfo(uint nr);
 
	GRFParameterInfo(GRFParameterInfo &info);
 
	~GRFParameterInfo();
 
	struct GRFText *name;  ///< The name of this parameter
 
	struct GRFText *desc;  ///< The description of this parameter
 
	GRFTextList name;      ///< The name of this parameter
 
	GRFTextList desc;      ///< The description of this parameter
 
	GRFParameterType type; ///< The type of this parameter
 
	uint32 min_value;      ///< The minimal value this parameter can have
 
	uint32 max_value;      ///< The maximal value of this parameter
 
@@ -131,7 +141,7 @@ struct GRFParameterInfo {
 
	byte param_nr;         ///< GRF parameter to store content in
 
	byte first_bit;        ///< First bit to use in the GRF parameter
 
	byte num_bit;          ///< Number of bits to use for this parameter
 
	SmallMap<uint32, struct GRFText *> value_names; ///< Names for each value.
 
	SmallMap<uint32, GRFTextList> value_names; ///< Names for each value.
 
	bool complete_labels;  ///< True if all values have a label.
 

	
 
	uint32 GetValue(struct GRFConfig *config) const;
 
@@ -139,14 +149,6 @@ struct GRFParameterInfo {
 
	void Finalize();
 
};
 

	
 
/** Reference counted wrapper around a GRFText pointer. */
 
struct GRFTextWrapper : public SimpleCountedObject {
 
	struct GRFText *text; ///< The actual text
 

	
 
	GRFTextWrapper();
 
	~GRFTextWrapper();
 
};
 

	
 
/** Information about GRF, used in the game and (part of it) in savegames */
 
struct GRFConfig : ZeroedMemoryAllocator {
 
	GRFConfig(const char *filename = nullptr);
 
@@ -156,9 +158,9 @@ struct GRFConfig : ZeroedMemoryAllocator
 
	GRFIdentifier ident;                        ///< grfid and md5sum to uniquely identify newgrfs
 
	uint8 original_md5sum[16];                  ///< MD5 checksum of original file if only a 'compatible' file was loaded
 
	char *filename;                             ///< Filename - either with or without full path
 
	GRFTextWrapper *name;                       ///< NOSAVE: GRF name (Action 0x08)
 
	GRFTextWrapper *info;                       ///< NOSAVE: GRF info (author, copyright, ...) (Action 0x08)
 
	GRFTextWrapper *url;                        ///< NOSAVE: URL belonging to this GRF.
 
	GRFTextWrapper name;                        ///< NOSAVE: GRF name (Action 0x08)
 
	GRFTextWrapper info;                        ///< NOSAVE: GRF info (author, copyright, ...) (Action 0x08)
 
	GRFTextWrapper url;                         ///< NOSAVE: URL belonging to this GRF.
 
	GRFError *error;                            ///< NOSAVE: Error/Warning during GRF loading (Action 0x0B)
 

	
 
	uint32 version;                             ///< NOSAVE: Version a NewGRF can set so only the newest NewGRF is shown
 
@@ -229,7 +231,7 @@ void ShowNewGRFSettings(bool editable, b
 

	
 
/** For communication about GRFs over the network */
 
#define UNKNOWN_GRF_NAME_PLACEHOLDER "<Unknown>"
 
GRFTextWrapper *FindUnknownGRFName(uint32 grfid, uint8 *md5sum, bool create);
 
GRFTextWrapper FindUnknownGRFName(uint32 grfid, uint8 *md5sum, bool create);
 

	
 
void UpdateNewGRFScanStatus(uint num, const char *name);
 
bool UpdateNewGRFConfigPalette(int32 p1 = 0);
src/newgrf_text.cpp
Show inline comments
 
@@ -60,89 +60,6 @@ enum GRFExtendedLanguages {
 
	GRFLX_UNSPECIFIED = 0x7F,
 
};
 

	
 
/**
 
 * Element of the linked list.
 
 * Each of those elements represent the string,
 
 * but according to a different lang.
 
 */
 
struct GRFText {
 
public:
 
	/**
 
	 * Allocate, and assign a new GRFText with the given text.
 
	 * As these strings can have string terminations in them, e.g.
 
	 * due to "choice lists" we (sometimes) cannot rely on detecting
 
	 * the length by means of strlen. Also, if the length of already
 
	 * known not scanning the whole string is more efficient.
 
	 * @param langid The language of the text.
 
	 * @param text   The text to store in the new GRFText.
 
	 * @param len    The length of the text.
 
	 */
 
	static GRFText *New(byte langid, const char *text, size_t len)
 
	{
 
		return new (len) GRFText(langid, text, len);
 
	}
 

	
 
	/**
 
	 * Create a copy of this GRFText.
 
	 * @param orig the grftext to copy.
 
	 * @return an exact copy of the given text.
 
	 */
 
	static GRFText *Copy(GRFText *orig)
 
	{
 
		return GRFText::New(orig->langid, orig->text, orig->len);
 
	}
 

	
 
	/**
 
	 * Helper allocation function to disallow something.
 
	 * Don't allow simple 'news'; they wouldn't have enough memory.
 
	 * @param size the amount of space not to allocate.
 
	 */
 
	void *operator new(size_t size)
 
	{
 
		NOT_REACHED();
 
	}
 

	
 
	/**
 
	 * Free the memory we allocated.
 
	 * @param p memory to free.
 
	 */
 
	void operator delete(void *p)
 
	{
 
		free(p);
 
	}
 
private:
 
	/**
 
	 * Actually construct the GRFText.
 
	 * @param langid_ The language of the text.
 
	 * @param text_   The text to store in this GRFText.
 
	 * @param len_    The length of the text to store.
 
	 */
 
	GRFText(byte langid_, const char *text_, size_t len_) : next(nullptr), len(len_), langid(langid_)
 
	{
 
		/* We need to use memcpy instead of strcpy due to
 
		 * the possibility of "choice lists" and therefore
 
		 * intermediate string terminators. */
 
		memcpy(this->text, text_, len);
 
	}
 

	
 
	/**
 
	 * Allocate memory for this class.
 
	 * @param size the size of the instance
 
	 * @param extra the extra memory for the text
 
	 * @return the requested amount of memory for both the instance and the text
 
	 */
 
	void *operator new(size_t size, size_t extra)
 
	{
 
		return MallocT<byte>(size + extra);
 
	}
 

	
 
public:
 
	GRFText *next; ///< The next GRFText in this chain.
 
	size_t len;    ///< The length of the stored string, used for copying.
 
	byte langid;   ///< The language associated with this GRFText.
 
	char text[];   ///< The actual (translated) text.
 
};
 

	
 

	
 
/**
 
 * Holder of the above structure.
 
@@ -153,7 +70,7 @@ struct GRFTextEntry {
 
	uint32 grfid;
 
	uint16 stringid;
 
	StringID def_string;
 
	GRFText *textholder;
 
	GRFTextList textholder;
 
};
 

	
 

	
 
@@ -576,26 +493,23 @@ string_end:
 
}
 

	
 
/**
 
 * Add a GRFText to a GRFText list.
 
 * Add a new text to a GRFText list.
 
 * @param list The list where the text should be added to.
 
 * @param text_to_add The GRFText to add to the list.
 
 * @param langid The The language of the new text.
 
 * @param text_to_add The text to add to the list.
 
 */
 
void AddGRFTextToList(GRFText **list, GRFText *text_to_add)
 
static void AddGRFTextToList(GRFTextList &list, byte langid, const std::string &text_to_add)
 
{
 
	GRFText **ptext, *text;
 

	
 
	/* Loop through all languages and see if we can replace a string */
 
	for (ptext = list; (text = *ptext) != nullptr; ptext = &text->next) {
 
		if (text->langid == text_to_add->langid) {
 
			text_to_add->next = text->next;
 
			*ptext = text_to_add;
 
			delete text;
 
	for (auto &text : list) {
 
		if (text.langid == langid) {
 
			text.text = text_to_add;
 
			return;
 
		}
 
	}
 

	
 
	/* If a string wasn't replaced, then we must append the new string */
 
	*ptext = text_to_add;
 
	list.push_back(GRFText{ langid, text_to_add });
 
}
 

	
 
/**
 
@@ -607,14 +521,29 @@ void AddGRFTextToList(GRFText **list, GR
 
 * @param text_to_add The text to add to the list.
 
 * @note All text-codes will be translated.
 
 */
 
void AddGRFTextToList(struct GRFText **list, byte langid, uint32 grfid, bool allow_newlines, const char *text_to_add)
 
void AddGRFTextToList(GRFTextList &list, byte langid, uint32 grfid, bool allow_newlines, const char *text_to_add)
 
{
 
	int len;
 
	char *translatedtext = TranslateTTDPatchCodes(grfid, langid, allow_newlines, text_to_add, &len);
 
	GRFText *newtext = GRFText::New(langid, translatedtext, len);
 
	std::string newtext(translatedtext, len);
 
	free(translatedtext);
 

	
 
	AddGRFTextToList(list, newtext);
 
	AddGRFTextToList(list, langid, newtext);
 
}
 

	
 
/**
 
 * Add a string to a GRFText list.
 
 * @param list The list where the text should be added to.
 
 * @param langid The language of the new text.
 
 * @param grfid The grfid where this string is defined.
 
 * @param allow_newlines Whether newlines are allowed in this string.
 
 * @param text_to_add The text to add to the list.
 
 * @note All text-codes will be translated.
 
 */
 
void AddGRFTextToList(GRFTextWrapper &list, byte langid, uint32 grfid, bool allow_newlines, const char *text_to_add)
 
{
 
	if (!list) list.reset(new GRFTextList());
 
	AddGRFTextToList(*list, langid, grfid, allow_newlines, text_to_add);
 
}
 

	
 
/**
 
@@ -623,25 +552,10 @@ void AddGRFTextToList(struct GRFText **l
 
 * @param list The list where the text should be added to.
 
 * @param text_to_add The text to add to the list.
 
 */
 
void AddGRFTextToList(struct GRFText **list, const char *text_to_add)
 
void AddGRFTextToList(GRFTextWrapper &list, const char *text_to_add)
 
{
 
	AddGRFTextToList(list, GRFText::New(0x7F, text_to_add, strlen(text_to_add) + 1));
 
}
 

	
 
/**
 
 * Create a copy of this GRFText list.
 
 * @param orig The GRFText list to copy.
 
 * @return A duplicate of the given GRFText.
 
 */
 
GRFText *DuplicateGRFText(GRFText *orig)
 
{
 
	GRFText *newtext = nullptr;
 
	GRFText **ptext = &newtext;
 
	for (; orig != nullptr; orig = orig->next) {
 
		*ptext = GRFText::Copy(orig);
 
		ptext = &(*ptext)->next;
 
	}
 
	return newtext;
 
	if (!list) list.reset(new GRFTextList());
 
	AddGRFTextToList(*list, GRFLX_UNSPECIFIED, std::string(text_to_add));
 
}
 

	
 
/**
 
@@ -681,22 +595,20 @@ StringID AddGRFString(uint32 grfid, uint
 

	
 
	int len;
 
	translatedtext = TranslateTTDPatchCodes(grfid, langid_to_add, allow_newlines, text_to_add, &len);
 

	
 
	GRFText *newtext = GRFText::New(langid_to_add, translatedtext, len);
 

	
 
	std::string newtext(translatedtext, len);
 
	free(translatedtext);
 

	
 
	/* If we didn't find our stringid and grfid in the list, allocate a new id */
 
	if (id == _num_grf_texts) _num_grf_texts++;
 

	
 
	if (_grf_text[id].textholder == nullptr) {
 
	if (_grf_text[id].textholder.empty()) {
 
		_grf_text[id].grfid      = grfid;
 
		_grf_text[id].stringid   = stringid;
 
		_grf_text[id].def_string = def_string;
 
	}
 
	AddGRFTextToList(&_grf_text[id].textholder, newtext);
 
	AddGRFTextToList(_grf_text[id].textholder, langid_to_add, newtext);
 

	
 
	grfmsg(3, "Added 0x%X: grfid %08X string 0x%X lang 0x%X string '%s' (%X)", id, grfid, stringid, newtext->langid, newtext->text, MakeStringID(TEXT_TAB_NEWGRF_START, id));
 
	grfmsg(3, "Added 0x%X: grfid %08X string 0x%X lang 0x%X string '%s' (%X)", id, grfid, stringid, langid_to_add, newtext.c_str(), MakeStringID(TEXT_TAB_NEWGRF_START, id));
 

	
 
	return MakeStringID(TEXT_TAB_NEWGRF_START, id);
 
}
 
@@ -721,20 +633,20 @@ StringID GetGRFStringID(uint32 grfid, St
 
 * current language it is returned, otherwise the default translation
 
 * is returned. If there is neither a default nor a translation for the
 
 * current language nullptr is returned.
 
 * @param text The GRFText to get the string from.
 
 * @param text_list The GRFTextList to get the string from.
 
 */
 
const char *GetGRFStringFromGRFText(const GRFText *text)
 
const char *GetGRFStringFromGRFText(const GRFTextList &text_list)
 
{
 
	const char *default_text = nullptr;
 

	
 
	/* Search the list of lang-strings of this stringid for current lang */
 
	for (; text != nullptr; text = text->next) {
 
		if (text->langid == _currentLangID) return text->text;
 
	for (const auto &text : text_list) {
 
		if (text.langid == _currentLangID) return text.text.c_str();
 

	
 
		/* If the current string is English or American, set it as the
 
		 * fallback language if the specific language isn't available. */
 
		if (text->langid == GRFLX_UNSPECIFIED || (default_text == nullptr && (text->langid == GRFLX_ENGLISH || text->langid == GRFLX_AMERICAN))) {
 
			default_text = text->text;
 
		if (text.langid == GRFLX_UNSPECIFIED || (default_text == nullptr && (text.langid == GRFLX_ENGLISH || text.langid == GRFLX_AMERICAN))) {
 
			default_text = text.text.c_str();
 
		}
 
	}
 

	
 
@@ -742,6 +654,18 @@ const char *GetGRFStringFromGRFText(cons
 
}
 

	
 
/**
 
 * Get a C-string from a GRFText-list. If there is a translation for the
 
 * current language it is returned, otherwise the default translation
 
 * is returned. If there is neither a default nor a translation for the
 
 * current language nullptr is returned.
 
 * @param text The GRFTextList to get the string from.
 
 */
 
const char *GetGRFStringFromGRFText(const GRFTextWrapper &text)
 
{
 
	return text ? GetGRFStringFromGRFText(*text) : nullptr;
 
}
 

	
 
/**
 
 * Get a C-string from a stringid set by a newgrf.
 
 */
 
const char *GetGRFStringPtr(uint16 stringid)
 
@@ -783,19 +707,6 @@ bool CheckGrfLangID(byte lang_id, byte g
 
}
 

	
 
/**
 
 * Delete all items of a linked GRFText list.
 
 * @param grftext the head of the list to delete
 
 */
 
void CleanUpGRFText(GRFText *grftext)
 
{
 
	while (grftext != nullptr) {
 
		GRFText *grftext2 = grftext->next;
 
		delete grftext;
 
		grftext = grftext2;
 
	}
 
}
 

	
 
/**
 
 * House cleaning.
 
 * Remove all strings and reset the text counter.
 
 */
 
@@ -804,10 +715,9 @@ void CleanUpStrings()
 
	uint id;
 

	
 
	for (id = 0; id < _num_grf_texts; id++) {
 
		CleanUpGRFText(_grf_text[id].textholder);
 
		_grf_text[id].grfid      = 0;
 
		_grf_text[id].stringid   = 0;
 
		_grf_text[id].textholder = nullptr;
 
		_grf_text[id].textholder.clear();
 
	}
 

	
 
	_num_grf_texts = 0;
src/newgrf_text.h
Show inline comments
 
@@ -14,26 +14,39 @@
 
#include "strings_type.h"
 
#include "core/smallvec_type.hpp"
 
#include "table/control_codes.h"
 
#include <utility>
 
#include <vector>
 
#include <string>
 

	
 
/** This character, the thorn ('รพ'), indicates a unicode string to NFO. */
 
static const WChar NFO_UTF8_IDENTIFIER = 0x00DE;
 

	
 
/** A GRF text with associated language ID. */
 
struct GRFText {
 
	byte langid;      ///< The language associated with this GRFText.
 
	std::string text; ///< The actual (translated) text.
 
};
 

	
 
/** A GRF text with a list of translations. */
 
typedef std::vector<GRFText> GRFTextList;
 
/** Reference counted wrapper around a GRFText pointer. */
 
typedef std::shared_ptr<GRFTextList> GRFTextWrapper;
 

	
 
StringID AddGRFString(uint32 grfid, uint16 stringid, byte langid, bool new_scheme, bool allow_newlines, const char *text_to_add, StringID def_string);
 
StringID GetGRFStringID(uint32 grfid, StringID stringid);
 
const char *GetGRFStringFromGRFText(const struct GRFText *text);
 
const char *GetGRFStringFromGRFText(const GRFTextList &text_list);
 
const char *GetGRFStringFromGRFText(const GRFTextWrapper &text);
 
const char *GetGRFStringPtr(uint16 stringid);
 
void CleanUpStrings();
 
void SetCurrentGrfLangID(byte language_id);
 
char *TranslateTTDPatchCodes(uint32 grfid, uint8 language_id, bool allow_newlines, const char *str, int *olen = nullptr, StringControlCode byte80 = SCC_NEWGRF_PRINT_WORD_STRING_ID);
 
struct GRFText *DuplicateGRFText(struct GRFText *orig);
 
void AddGRFTextToList(struct GRFText **list, struct GRFText *text_to_add);
 
void AddGRFTextToList(struct GRFText **list, byte langid, uint32 grfid, bool allow_newlines, const char *text_to_add);
 
void AddGRFTextToList(struct GRFText **list, const char *text_to_add);
 
void CleanUpGRFText(struct GRFText *grftext);
 
void AddGRFTextToList(GRFTextList &list, byte langid, uint32 grfid, bool allow_newlines, const char *text_to_add);
 
void AddGRFTextToList(GRFTextWrapper &list, byte langid, uint32 grfid, bool allow_newlines, const char *text_to_add);
 
void AddGRFTextToList(GRFTextWrapper &list, const char *text_to_add);
 

	
 
bool CheckGrfLangID(byte lang_id, byte grf_version);
 

	
 
void StartTextRefStackUsage(const GRFFile *grffile, byte numEntries, const uint32 *values = nullptr);
 
void StartTextRefStackUsage(const struct GRFFile *grffile, byte numEntries, const uint32 *values = nullptr);
 
void StopTextRefStackUsage();
 
void RewindTextRefStack();
 
bool UsingNewGRFTextStack();
0 comments (0 inline, 0 general)