From 18f0f1d81d06fc504965a6bedcd8e20e06b96bd7 Mon Sep 17 00:00:00 2001 From: rubidium Date: Tue, 16 Nov 2010 21:03:39 +0000 Subject: [PATCH] (svn r21216) -Feature: [NewGRF] Allow specifying a "choice list" for plurals --- src/newgrf.cpp | 14 +++++++++++++- src/newgrf_text.cpp | 19 ++++++++++++------- src/newgrf_text.h | 1 + 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 0b9382732c..fca8f96bf5 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -1911,7 +1911,8 @@ static ChangeInfoResult GlobalVarChangeInfo(uint gvid, int numinfo, int prop, By break; case 0x13: // Gender translation table - case 0x14: { // Case translation table + case 0x14: // Case translation table + case 0x15: { // Plural form translation uint curidx = gvid + i; // The current index, i.e. language. const LanguageMetadata *lang = curidx < MAX_LANG ? GetLanguage(curidx) : NULL; if (lang == NULL) { @@ -1925,6 +1926,16 @@ static ChangeInfoResult GlobalVarChangeInfo(uint gvid, int numinfo, int prop, By if (_cur_grffile->language_map == NULL) _cur_grffile->language_map = new LanguageMap[MAX_LANG]; + if (prop == 0x15) { + uint plural_form = buf->ReadByte(); + if (plural_form >= LANGUAGE_MAX_PLURAL) { + grfmsg(1, "GlobalVarChanceInfo: Plural form %d is out of range, ignoring", plural_form); + } else { + _cur_grffile->language_map[curidx].plural_form = plural_form; + } + break; + } + byte newgrf_id = buf->ReadByte(); // The NewGRF (custom) identifier. while (newgrf_id != 0) { const char *name = buf->ReadString(); // The name for the OpenTTD identifier. @@ -1975,6 +1986,7 @@ static ChangeInfoResult GlobalVarReserveInfo(uint gvid, int numinfo, int prop, B for (int i = 0; i < numinfo; i++) { switch (prop) { case 0x08: // Cost base factor + case 0x15: // Plural form translation buf->ReadByte(); break; diff --git a/src/newgrf_text.cpp b/src/newgrf_text.cpp index 732261c9c1..a1045056f9 100644 --- a/src/newgrf_text.cpp +++ b/src/newgrf_text.cpp @@ -263,7 +263,7 @@ struct UnmappedChoiceList : ZeroedMemoryAllocator { * Initialise the mapping. * @param type The type of mapping. * @param old_d The old begin of the string, i.e. from where to start writing again. - * @param offset The offset to get the gender from. + * @param offset The offset to get the plural/gender from. */ UnmappedChoiceList(StringControlCode type, char *old_d, int offset) : type(type), old_d(old_d), offset(offset) @@ -272,7 +272,7 @@ struct UnmappedChoiceList : ZeroedMemoryAllocator { StringControlCode type; ///< The type of choice list. char *old_d; ///< The old/original location of the "d" local variable. - int offset; ///< The offset for the gender form. + int offset; ///< The offset for the plural/gender form. /** Mapping of NewGRF supplied ID to the different strings in the choice list. */ SmallMap strings; @@ -292,7 +292,7 @@ struct UnmappedChoiceList : ZeroedMemoryAllocator { } char *d = old_d; - if (lm == NULL) { + if (lm == NULL && this->type != SCC_PLURAL_LIST) { NOT_REACHED(); /* In case there is no mapping, just ignore everything but the default. */ int len = strlen(this->strings[0]); @@ -343,6 +343,10 @@ struct UnmappedChoiceList : ZeroedMemoryAllocator { d += len; *d++ = '\0'; } else { + if (this->type == SCC_PLURAL_LIST) { + *d++ = lm->plural_form; + } + /* * Format for choice list: * @@ -352,12 +356,12 @@ struct UnmappedChoiceList : ZeroedMemoryAllocator { *d++ = this->offset - 0x80; /* "" */ - int count = _current_language->num_genders; + int count = (this->type == SCC_GENDER_LIST ? _current_language->num_genders : LANGUAGE_MAX_PLURAL_FORMS); *d++ = count; /* "" */ for (int i = 0; i < count; i++) { - int idx = lm->GetReverseMapping(i, true); + int idx = (this->type == SCC_GENDER_LIST ? lm->GetReverseMapping(i, true) : i + 1); const char *str = this->strings[this->strings.Contains(idx) ? idx : 0]; int len = strlen(str) + 1; if (len > 0xFF) grfmsg(1, "choice list string is too long"); @@ -366,7 +370,7 @@ struct UnmappedChoiceList : ZeroedMemoryAllocator { /* "" */ for (int i = 0; i < count; i++) { - int idx = lm->GetReverseMapping(i, true); + int idx = (this->type == SCC_GENDER_LIST ? lm->GetReverseMapping(i, true) : i + 1); const char *str = this->strings[this->strings.Contains(idx) ? idx : 0]; int len = strlen(str); memcpy(d, str, len); @@ -546,11 +550,12 @@ char *TranslateTTDPatchCodes(uint32 grfid, uint8 language_id, const char *str, i case 0x13: case 0x14: + case 0x15: if (mapping != NULL) { grfmsg(1, "choice lists can't be stacked, it's going to get messy now..."); if (code != 0x14) str++; } else { - static const StringControlCode mp[] = { SCC_GENDER_LIST, SCC_SWITCH_CASE }; + static const StringControlCode mp[] = { SCC_GENDER_LIST, SCC_SWITCH_CASE, SCC_PLURAL_LIST }; mapping = new UnmappedChoiceList(mp[code - 0x13], d, code == 0x14 ? 0 : *str++); } break; diff --git a/src/newgrf_text.h b/src/newgrf_text.h index dc069a93ef..a4c5f61237 100644 --- a/src/newgrf_text.h +++ b/src/newgrf_text.h @@ -59,6 +59,7 @@ struct LanguageMap { * both cases. Thus we are basically implementing a multi-map. */ SmallVector gender_map; ///< Mapping of NewGRF and OpenTTD IDs for genders. SmallVector case_map; ///< Mapping of NewGRF and OpenTTD IDs for cases. + int plural_form; ///< The plural form used for this language. int GetMapping(int newgrf_id, bool gender) const; int GetReverseMapping(int openttd_id, bool gender) const;