/* * CGeneralTextHandler.h, part of VCMI engine * * Authors: listed in file AUTHORS in main folder * * License: GNU General Public License v2.0 or later * Full text of license available in license.txt file, in main folder * */ #pragma once #include "JsonNode.h" VCMI_LIB_NAMESPACE_BEGIN /// Namespace that provides utilites for unicode support (UTF-8) namespace Unicode { /// evaluates size of UTF-8 character size_t DLL_LINKAGE getCharacterSize(char firstByte); /// test if character is a valid UTF-8 symbol /// maxSize - maximum number of bytes this symbol may consist from ( = remainer of string) bool DLL_LINKAGE isValidCharacter(const char * character, size_t maxSize); /// test if text contains ASCII-string (no need for unicode conversion) bool DLL_LINKAGE isValidASCII(const std::string & text); bool DLL_LINKAGE isValidASCII(const char * data, size_t size); /// test if text contains valid UTF-8 sequence bool DLL_LINKAGE isValidString(const std::string & text); bool DLL_LINKAGE isValidString(const char * data, size_t size); /// converts text to unicode from specified encoding or from one specified in settings std::string DLL_LINKAGE toUnicode(const std::string & text); std::string DLL_LINKAGE toUnicode(const std::string & text, const std::string & encoding); /// converts text from unicode to specified encoding or to one specified in settings /// NOTE: usage of these functions should be avoided if possible std::string DLL_LINKAGE fromUnicode(const std::string & text); std::string DLL_LINKAGE fromUnicode(const std::string & text, const std::string & encoding); ///delete (amount) UTF characters from right DLL_LINKAGE void trimRight(std::string & text, const size_t amount = 1); }; class CInputStream; /// Parser for any text files from H3 class DLL_LINKAGE CLegacyConfigParser { std::unique_ptr data; char * curr; char * end; void init(const std::unique_ptr & input); /// extracts part of quoted string. std::string extractQuotedPart(); /// extracts quoted string. Any end of lines are ignored, double-quote is considered as "escaping" std::string extractQuotedString(); /// extracts non-quoted string std::string extractNormalString(); /// reads "raw" string without encoding conversion std::string readRawString(); public: /// read one entry from current line. Return ""/0 if end of line reached std::string readString(); float readNumber(); template std::vector readNumArray(size_t size) { std::vector ret; ret.reserve(size); while (size--) ret.push_back((numeric)readNumber()); return ret; } /// returns true if next entry is empty bool isNextEntryEmpty() const; /// end current line bool endLine(); CLegacyConfigParser(std::string URI); CLegacyConfigParser(const std::unique_ptr & input); }; class CGeneralTextHandler; /// Small wrapper that provides text access API compatible with old code class DLL_LINKAGE LegacyTextContainer { CGeneralTextHandler & owner; std::string basePath; public: LegacyTextContainer(CGeneralTextHandler & owner, std::string const & basePath); std::string operator [](size_t index) const; }; /// Small wrapper that provides help text access API compatible with old code class DLL_LINKAGE LegacyHelpContainer { CGeneralTextHandler & owner; std::string basePath; public: LegacyHelpContainer(CGeneralTextHandler & owner, std::string const & basePath); std::pair operator[](size_t index) const; }; class TextIdentifier { std::string identifier; public: std::string const & get() const { return identifier; } TextIdentifier(const char * id): identifier(id) {} TextIdentifier(std::string const & id): identifier(id) {} template TextIdentifier(std::string const & id, size_t index, T ... rest): TextIdentifier(id + '.' + std::to_string(index), rest ... ) {} template TextIdentifier(std::string const & id, std::string const & id2, T ... rest): TextIdentifier(id + '.' + id2, rest ... ) {} }; /// Handles all text-related data in game class DLL_LINKAGE CGeneralTextHandler { /// map identifier -> localization std::unordered_map stringsLocalizations; /// map identifier -> localization, high-priority strings from translation json std::unordered_map stringsOverrides; void readToVector(const std::string & sourceID, const std::string & sourceName); /// number of scenarios in specific campaign. TODO: move to a better location std::vector scenariosCountPerCampaign; /// Attempts to detect encoding & language of H3 files void detectInstallParameters() const; public: /// Loads translation from provided json /// Any entries loaded by this will have priority over texts registered normally void loadTranslationOverrides(JsonNode const & file); /// add selected string to internal storage void registerString(const TextIdentifier & UID, const std::string & localized); /// add selected string to internal storage as high-priority strings void registerStringOverride(const TextIdentifier & UID, const std::string & localized); // returns true if identifier with such name was registered, even if not translated to current language // not required right now, can be added if necessary // bool identifierExists( const std::string identifier) const; /// returns translated version of a string that can be displayed to user template std::string translate(std::string arg1, Args ... args) const { TextIdentifier id(arg1, args ...); return deserialize(id); } /// converts identifier into user-readable string const std::string & deserialize(const TextIdentifier & identifier) const; /// Debug method, dumps all currently known texts into console using Json-like format void dumpAllTexts(); LegacyTextContainer allTexts; LegacyTextContainer arraytxt; LegacyTextContainer primarySkillNames; LegacyTextContainer jktexts; LegacyTextContainer heroscrn; LegacyTextContainer overview;//text for Kingdom Overview window LegacyTextContainer colors; //names of player colors ("red",...) LegacyTextContainer capColors; //names of player colors with first letter capitalized ("Red",...) LegacyTextContainer turnDurations; //turn durations for pregame (1 Minute ... Unlimited) //towns LegacyTextContainer tcommands, hcommands, fcommands; //texts for town screen, town hall screen and fort screen LegacyTextContainer tavernInfo; LegacyTextContainer tavernRumors; LegacyTextContainer qeModCommands; LegacyHelpContainer zelp; LegacyTextContainer lossCondtions; LegacyTextContainer victoryConditions; //objects LegacyTextContainer advobtxt; LegacyTextContainer restypes; //names of resources LegacyTextContainer randsign; LegacyTextContainer seerEmpty; LegacyTextContainer seerNames; LegacyTextContainer tentColors; //sec skills LegacyTextContainer levels; //commanders LegacyTextContainer znpc00; //more or less useful content of that file std::vector findStringsWithPrefix(std::string const & prefix); int32_t pluralText(const int32_t textIndex, const int32_t count) const; size_t getCampaignLength(size_t campaignID) const; CGeneralTextHandler(); CGeneralTextHandler(const CGeneralTextHandler&) = delete; CGeneralTextHandler operator=(const CGeneralTextHandler&) = delete; /// Returns name of language preferred by user static std::string getInstalledLanguage(); /// Returns name of encoding of Heroes III text files static std::string getInstalledEncoding(); }; VCMI_LIB_NAMESPACE_END