summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/newgrf.cpp58
-rw-r--r--src/newgrf.h2
-rw-r--r--src/newgrf_text.h19
3 files changed, 79 insertions, 0 deletions
diff --git a/src/newgrf.cpp b/src/newgrf.cpp
index bb77635d8..6c758c9dd 100644
--- a/src/newgrf.cpp
+++ b/src/newgrf.cpp
@@ -47,6 +47,7 @@
#include "genworld.h"
#include "gui.h"
#include "vehicle_func.h"
+#include "language.h"
#include "table/strings.h"
#include "table/build_industry.h"
@@ -1896,6 +1897,55 @@ static ChangeInfoResult GlobalVarChangeInfo(uint gvid, int numinfo, int prop, By
buf->Skip(4);
break;
+ case 0x13: // Gender translation table
+ case 0x14: { // Case translation table
+ uint curidx = gvid + i; // The current index, i.e. language.
+ const LanguageMetadata *lang = curidx < MAX_LANG ? GetLanguage(curidx) : NULL;
+ if (lang == NULL) {
+ grfmsg(1, "GlobalVarChangeInfo: Language %d is not known, ignoring", curidx);
+ /* Skip over the data. */
+ while (buf->ReadByte() != 0) {
+ buf->ReadString();
+ }
+ break;
+ }
+
+ if (_cur_grffile->language_map == NULL) _cur_grffile->language_map = new LanguageMap[MAX_LANG];
+
+ byte newgrf_id = buf->ReadByte(); // The NewGRF (custom) identifier.
+ while (newgrf_id != 0) {
+ const char *name = buf->ReadString(); // The name for the OpenTTD identifier.
+
+ /* We'll just ignore the UTF8 identifier character. This is (fairly)
+ * safe as OpenTTD's strings gender/cases are usually in ASCII which
+ * is just a subset of UTF8, or they need the bigger UTF8 characters
+ * such as Cyrillic. Thus we will simply assume they're all UTF8. */
+ WChar c;
+ size_t len = Utf8Decode(&c, name);
+ if (c == NFO_UTF8_IDENTIFIER) name += len;
+
+ LanguageMap::Mapping map;
+ map.newgrf_id = newgrf_id;
+ if (prop == 0x13) {
+ map.openttd_id = lang->GetGenderIndex(name);
+ if (map.openttd_id >= MAX_NUM_GENDERS) {
+ grfmsg(1, "GlobalVarChangeInfo: Gender name %s is not known, ignoring", name);
+ } else {
+ *_cur_grffile->language_map[curidx].gender_map.Append() = map;
+ }
+ } else {
+ map.openttd_id = lang->GetCaseIndex(name);
+ if (map.openttd_id >= MAX_NUM_CASES) {
+ grfmsg(1, "GlobalVarChangeInfo: Case name %s is not known, ignoring", name);
+ } else {
+ *_cur_grffile->language_map[curidx].case_map.Append() = map;
+ }
+ }
+ newgrf_id = buf->ReadByte();
+ }
+ break;
+ }
+
default:
ret = CIR_UNKNOWN;
break;
@@ -1972,6 +2022,13 @@ static ChangeInfoResult GlobalVarReserveInfo(uint gvid, int numinfo, int prop, B
break;
}
+ case 0x13: // Gender translation table
+ case 0x14: // Case translation table
+ while (buf->ReadByte() != 0) {
+ buf->ReadString();
+ }
+ break;
+
default:
ret = CIR_UNKNOWN;
break;
@@ -6990,6 +7047,7 @@ static void ResetNewGRF()
free(f->filename);
free(f->cargo_list);
free(f->railtype_list);
+ delete [] f->language_map;
free(f);
}
diff --git a/src/newgrf.h b/src/newgrf.h
index 5be03b8c4..4e7ef3f06 100644
--- a/src/newgrf.h
+++ b/src/newgrf.h
@@ -123,6 +123,8 @@ struct GRFFile {
RailTypeLabel *railtype_list;
RailType railtype_map[RAILTYPE_END];
+ struct LanguageMap *language_map; ///< Mappings related to the languages.
+
int traininfo_vehicle_pitch; ///< Vertical offset for draing train images in depot GUI and vehicle details
uint traininfo_vehicle_width; ///< Width (in pixels) of a 8/8 train vehicle in depot GUI and vehicle details
diff --git a/src/newgrf_text.h b/src/newgrf_text.h
index 2865bf706..90fcd719a 100644
--- a/src/newgrf_text.h
+++ b/src/newgrf_text.h
@@ -14,6 +14,7 @@
#include "string_type.h"
#include "strings_type.h"
+#include "core/smallvec_type.hpp"
/** This character, the thorn ('รพ'), indicates a unicode string to NFO. */
static const WChar NFO_UTF8_IDENTIFIER = 0x00DE;
@@ -42,4 +43,22 @@ uint RemapNewGRFStringControlCode(uint scc, char *buf_start, char **buff, const
StringID TTDPStringIDToOTTDStringIDMapping(StringID string);
+/** Mapping of language data between a NewGRF and OpenTTD. */
+struct LanguageMap {
+ /** Mapping between NewGRF and OpenTTD IDs. */
+ struct Mapping {
+ byte newgrf_id; ///< NewGRF's internal ID for a case/gender.
+ byte openttd_id; ///< OpenTTD's internal ID for a case/gender.
+ };
+
+ /* We need a vector and can't use SmallMap due to the fact that for "setting" a
+ * gender of a string or requesting a case for a substring we want to map from
+ * the NewGRF's internal ID to OpenTTD's ID whereas for the choice lists we map
+ * the genders/cases/plural OpenTTD IDs to the NewGRF's internal IDs. In this
+ * case a NewGRF developer/translator might want a different translation for
+ * both cases. Thus we are basically implementing a multi-map. */
+ SmallVector<Mapping, 1> gender_map; ///< Mapping of NewGRF and OpenTTD IDs for genders.
+ SmallVector<Mapping, 1> case_map; ///< Mapping of NewGRF and OpenTTD IDs for cases.
+};
+
#endif /* NEWGRF_TEXT_H */