mirror of https://github.com/OpenTTD/OpenTTD.git
Codechange: Replace custom linked list for GRF texts with STL vectors and strings.
This commit is contained in:
parent
f2b40f40aa
commit
43cd892e0c
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -426,9 +426,9 @@ void ClientNetworkUDPSocketHandler::Receive_SERVER_NEWGRFS(Packet *p, NetworkAdd
|
|||
/* 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::HandleIncomingNetworkGameInfoGRFConfig(GRFCo
|
|||
/* 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);
|
||||
}
|
||||
|
|
|
@ -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(ByteReader *buf)
|
|||
/** 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; ///< The parameter which info is curren
|
|||
/** 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(ByteReader *buf)
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 &config) :
|
|||
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 GRFConfig &src)
|
|||
*/
|
||||
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
|
|||
*/
|
||||
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 nr) :
|
|||
param_nr(nr),
|
||||
first_bit(0),
|
||||
num_bit(32),
|
||||
value_names(),
|
||||
complete_labels(false)
|
||||
{}
|
||||
|
||||
|
@ -250,8 +229,8 @@ GRFParameterInfo::GRFParameterInfo(uint nr) :
|
|||
* @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(GRFParameterInfo &info) :
|
|||
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 *filename, size_t basepath_length, const
|
|||
_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 grfid, FindGRFConfigMode mode, const uint8
|
|||
|
||||
/** 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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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, bool show_params, bool exec_changes, GRFC
|
|||
|
||||
/** 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);
|
||||
|
|
|
@ -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, GRFText *text_to_add)
|
|||
* @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 **list, byte langid, uint32 grfid, bool all
|
|||
* @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, uint16 stringid, byte langid_to_add, bool ne
|
|||
|
||||
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,26 +633,38 @@ StringID GetGRFStringID(uint32 grfid, StringID stringid)
|
|||
* 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();
|
||||
}
|
||||
}
|
||||
|
||||
return default_text;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
@ -782,19 +706,6 @@ bool CheckGrfLangID(byte lang_id, byte grf_version)
|
|||
return (lang_id == _currentLangID || lang_id == GRFLX_UNSPECIFIED);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue