strgen: Allow inserting strings before as well as after

Use for viewport town label strings
This commit is contained in:
Jonathan G Rennison
2023-02-16 01:26:14 +00:00
parent ea589fca6e
commit 50a48b1264
8 changed files with 134 additions and 95 deletions

View File

@@ -244,6 +244,16 @@ void FileStringReader::HandlePragma(char *str)
LangString *ent = this->data.Find(str + 6);
if (ent != nullptr) {
this->data.insert_after = ent;
this->data.insert_before = nullptr;
} else {
error("Can't find string to insert after: '%s'", str + 6);
}
} else if (!memcmp(str, "before ", 7)) {
if (this->translation) error("Insert before is only allowed in the base translation.");
LangString *ent = this->data.Find(str + 7);
if (ent != nullptr) {
this->data.insert_after = nullptr;
this->data.insert_before = ent;
} else {
error("Can't find string to insert after: '%s'", str + 6);
}

View File

@@ -35,7 +35,8 @@ struct LangString {
int index; ///< The index in the language file.
int line; ///< Line of string in source-file.
Case *translated_case; ///< Cases of the translation.
std::unique_ptr<LangString> chain_next;
std::unique_ptr<LangString> chain_before;
std::unique_ptr<LangString> chain_after;
LangString *default_translation = nullptr;
LangString(const char *name, const char *english, size_t index, int line);
@@ -53,6 +54,7 @@ struct StringData {
int next_string_id; ///< The next string ID to allocate.
std::vector<std::unique_ptr<LangString>> string_store;
LangString *insert_before = nullptr;
LangString *insert_after = nullptr;
bool override_mode = false;
LangString *default_translation = nullptr;
@@ -97,6 +99,8 @@ struct StringReader {
* Start parsing the file.
*/
virtual void ParseFile();
void AssignIDs(size_t &next_id, LangString *ls);
};
/** Base class for writing the header, i.e. the STR_XXX to numeric value. */

View File

@@ -773,8 +773,8 @@ void StringReader::HandleString(char *str)
return;
}
if (this->data.next_string_id >= 0 && this->data.insert_after != nullptr) {
strgen_error("Cannot use insert_after and id at the same time: '%s'", str);
if (this->data.next_string_id >= 0 && (this->data.insert_after != nullptr || this->data.insert_before != nullptr)) {
strgen_error("Cannot use insert_after/insert_before and id at the same time: '%s'", str);
}
/* Allocate a new LangString */
@@ -789,7 +789,12 @@ void StringReader::HandleString(char *str)
if (this->data.insert_after != nullptr) {
LangString *cur = ls.get();
this->data.insert_after->chain_next = std::move(ls);
this->data.insert_after->chain_after = std::move(ls);
this->data.insert_after = cur;
} else if (this->data.insert_before != nullptr) {
LangString *cur = ls.get();
this->data.insert_before->chain_before = std::move(ls);
this->data.insert_before = nullptr;
this->data.insert_after = cur;
} else {
this->data.string_store.push_back(std::move(ls));
@@ -873,31 +878,37 @@ void StringReader::ParseFile()
/* Allocate IDs */
size_t next_id = 0;
for (const std::unique_ptr<LangString> &item : this->data.string_store) {
LangString *ls = item.get();
do {
if (ls->index >= 0) {
next_id = ls->index;
} else {
ls->index = next_id;
}
if ((size_t)ls->index >= this->data.max_strings) {
strgen_error("Too many strings, maximum allowed is " PRINTF_SIZE, this->data.max_strings);
return;
} else if (this->data.strings[ls->index] != nullptr) {
strgen_error("String ID 0x%X for '%s' already in use by '%s'", (uint)ls->index, ls->name, this->data.strings[ls->index]->name);
return;
} else {
this->data.strings[ls->index] = ls;
}
next_id++;
ls = ls->chain_next.get();
} while (ls != nullptr);
this->AssignIDs(next_id, item.get());
}
}
}
void StringReader::AssignIDs(size_t &next_id, LangString *ls)
{
do {
if (ls->chain_before) this->AssignIDs(next_id, ls->chain_before.get());
if (ls->index >= 0) {
next_id = ls->index;
} else {
ls->index = next_id;
}
if ((size_t)ls->index >= this->data.max_strings) {
strgen_error("Too many strings, maximum allowed is " PRINTF_SIZE, this->data.max_strings);
return;
} else if (this->data.strings[ls->index] != nullptr) {
strgen_error("String ID 0x%X for '%s' already in use by '%s'", (uint)ls->index, ls->name, this->data.strings[ls->index]->name);
return;
} else {
this->data.strings[ls->index] = ls;
}
next_id++;
ls = ls->chain_after.get();
} while (ls != nullptr);
}
/**
* Write the header information.
* @param data The data about the string.