1
0
Fork 0

Fix: [NewGRF] Plurals and genders did not work in strings with cases. (#13853)

pull/13874/head
frosch 2025-03-22 21:41:27 +01:00 committed by GitHub
parent d4ae0f70da
commit af49320637
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 20 additions and 11 deletions

View File

@ -128,7 +128,7 @@ struct UnmappedChoiceList {
* @param lm The current language mapping.
* @param dest Target to write to.
*/
void Flush(const LanguageMap *lm, std::ostringstream &dest)
void Flush(const LanguageMap *lm, std::stringstream &dest)
{
if (this->strings.find(0) == this->strings.end()) {
/* In case of a (broken) NewGRF without a default,
@ -251,10 +251,11 @@ std::string TranslateTTDPatchCodes(uint32_t grfid, uint8_t language_id, bool all
src += len;
}
/* Helper variable for a possible (string) mapping. */
std::optional<UnmappedChoiceList> mapping;
/* Helper variable for a possible (string) mapping of plural/gender and cases. */
std::optional<UnmappedChoiceList> mapping_pg, mapping_c;
std::optional<std::reference_wrapper<std::stringstream>> dest_c;
std::ostringstream dest;
std::stringstream dest;
std::ostreambuf_iterator<char> d(dest);
while (src != str.cend()) {
char32_t c;
@ -381,37 +382,44 @@ std::string TranslateTTDPatchCodes(uint32_t grfid, uint8_t language_id, bool all
case 0x10:
case 0x11:
if (str[0] == '\0') goto string_end;
if (!mapping.has_value()) {
if (!mapping_pg.has_value() && !mapping_c.has_value()) {
if (code == 0x10) src++; // Skip the index
GrfMsg(1, "choice list {} marker found when not expected", code == 0x10 ? "next" : "default");
break;
} else {
auto &mapping = mapping_pg ? mapping_pg : mapping_c;
int index = (code == 0x10 ? *src++ : 0);
if (mapping->strings.find(index) != mapping->strings.end()) {
GrfMsg(1, "duplicate choice list string, ignoring");
} else {
d = std::ostreambuf_iterator<char>(mapping->strings[index]);
if (!mapping_pg) dest_c = mapping->strings[index];
}
}
break;
case 0x12:
if (!mapping.has_value()) {
if (!mapping_pg.has_value() && !mapping_c.has_value()) {
GrfMsg(1, "choice list end marker found when not expected");
} else {
auto &mapping = mapping_pg ? mapping_pg : mapping_c;
auto &new_dest = mapping_pg && dest_c ? dest_c->get() : dest;
/* Now we can start flushing everything and clean everything up. */
mapping->Flush(LanguageMap::GetLanguageMap(grfid, language_id), dest);
mapping->Flush(LanguageMap::GetLanguageMap(grfid, language_id), new_dest);
if (!mapping_pg) dest_c.reset();
mapping.reset();
d = std::ostreambuf_iterator<char>(dest);
d = std::ostreambuf_iterator<char>(new_dest);
}
break;
case 0x13:
case 0x14:
case 0x15:
case 0x15: {
auto &mapping = code == 0x14 ? mapping_c : mapping_pg;
if (src[0] == '\0') goto string_end;
if (mapping.has_value()) {
/* Case mapping can have nested plural/gender mapping. Otherwise nesting is invalid. */
if (mapping.has_value() || mapping_pg.has_value()) {
GrfMsg(1, "choice lists can't be stacked, it's going to get messy now...");
if (code != 0x14) src++;
} else {
@ -419,6 +427,7 @@ std::string TranslateTTDPatchCodes(uint32_t grfid, uint8_t language_id, bool all
mapping.emplace(mp[code - 0x13], code == 0x14 ? 0 : *src++);
}
break;
}
case 0x16:
case 0x17:
@ -468,7 +477,7 @@ std::string TranslateTTDPatchCodes(uint32_t grfid, uint8_t language_id, bool all
}
string_end:
if (mapping.has_value()) {
if (mapping_pg.has_value() || mapping_c.has_value()) {
GrfMsg(1, "choice list was incomplete, the whole list is ignored");
}