diff --git a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUITextBoxMod.cpp b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUITextBoxMod.cpp index e5f1f574..9aaa02dc 100644 --- a/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUITextBoxMod.cpp +++ b/Sources/Plasma/FeatureLib/pfGameGUIMgr/pfGUITextBoxMod.cpp @@ -121,7 +121,7 @@ void pfGUITextBoxMod::IUpdate( void ) std::wstring drawStr; if (fUseLocalizationPath && !fLocalizationPath.IsEmpty() && pfLocalizationMgr::InstanceValid()) - drawStr = pfLocalizationMgr::Instance().GetString(fLocalizationPath.ToWchar().GetData()); + drawStr = pfLocalizationMgr::Instance().GetString(fLocalizationPath).ToWchar().GetData(); else { if( fText != nil ) diff --git a/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizationDataMgr.cpp b/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizationDataMgr.cpp index cf9ee052..60513871 100644 --- a/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizationDataMgr.cpp +++ b/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizationDataMgr.cpp @@ -62,10 +62,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include #include -// MinGW sucks -#if defined(_WIN32) && !defined(_MSC_VER) -# define swprintf _snwprintf -#endif ////////////////////////////////////////////////////////////////////// // @@ -120,11 +116,10 @@ protected: void IHandleAgeTag(const tagInfo & parentTag, const tagInfo & thisTag); void IHandleSetTag(const tagInfo & parentTag, const tagInfo & thisTag); void IHandleElementTag(const tagInfo & parentTag, const tagInfo & thisTag); - void IHandleTranslationTag(const tagInfo & parentTag, const tagInfo & thisTag); public: - LocalizationXMLFile() : fWeExploded(false), fFilename("") { } + LocalizationXMLFile() : fWeExploded(false) { } bool Parse(const plString & fileName); // returns false on failure void AddError(const plString & errorText); @@ -174,7 +169,7 @@ XML_Memory_Handling_Suite gHeapAllocator = { ////////////////////////////////////////////////////////////////////// //// XML Parsing functions /////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// -//metmet remove static + void XMLCALL LocalizationXMLFile::StartTag(void *userData, const XML_Char *element, const XML_Char **attributes) { plString wElement = plString::FromWchar(element); @@ -182,7 +177,7 @@ void XMLCALL LocalizationXMLFile::StartTag(void *userData, const XML_Char *eleme std::map wAttributes; for (int i = 0; attributes[i]; i += 2) - wAttributes[plString::FromWchar(static_cast(attributes[i]))] = plString::FromWchar(static_cast(attributes[i+1])); + wAttributes[plString::FromWchar(attributes[i])] = plString::FromWchar(attributes[i+1]); LocalizationXMLFile::tagInfo parentTag; if (!file->fTagStack.empty()) @@ -209,9 +204,9 @@ void XMLCALL LocalizationXMLFile::StartTag(void *userData, const XML_Char *eleme else if (wElement == "translation") file->IHandleTranslationTag(parentTag, newTag); else - file->AddError(plString::Format("Unknown tag %S found", wElement.c_str())); + file->AddError(plString::Format("Unknown tag %s found", wElement.c_str())); } -//metmet remove static and include the function inside LocalizationXMLFile + void XMLCALL LocalizationXMLFile::EndTag(void *userData, const XML_Char *element) { plString wElement = plString::FromWchar(element); @@ -238,7 +233,7 @@ void XMLCALL LocalizationXMLFile::EndTag(void *userData, const XML_Char *element file->fTagStack.pop(); } -//metmet remove static and include the function inside LocalizationXMLFile + void XMLCALL LocalizationXMLFile::HandleData(void *userData, const XML_Char *data, int stringLength) { LocalizationXMLFile *file = (LocalizationXMLFile*)userData; @@ -249,10 +244,10 @@ void XMLCALL LocalizationXMLFile::HandleData(void *userData, const XML_Char *dat // This gets all data between tags, including indentation and newlines // so we'll have to ignore data when we aren't expecting it (not in a translation tag) - plString wData = plString::FromWchar(data); + plString contents = plString::FromWchar(data, stringLength); // we must be in a translation tag since that's the only tag that doesn't ignore the contents - file->fData[file->fCurrentAge][file->fCurrentSet][file->fCurrentElement][file->fCurrentTranslation] += wData; + file->fData[file->fCurrentAge][file->fCurrentSet][file->fCurrentElement][file->fCurrentTranslation] += contents; } ////////////////////////////////////////////////////////////////////// @@ -265,7 +260,7 @@ void XMLCALL LocalizationXMLFile::HandleData(void *userData, const XML_Char *dat void LocalizationXMLFile::IHandleLocalizationsTag(const LocalizationXMLFile::tagInfo & parentTag, const LocalizationXMLFile::tagInfo & thisTag) { - if (parentTag.fTag != "") // we only allow tags at root level + if (!parentTag.fTag.IsEmpty()) // we only allow tags at root level { AddError("localizations tag only allowed at root level"); return; @@ -359,7 +354,7 @@ void LocalizationXMLFile::IHandleTranslationTag(const LocalizationXMLFile::tagIn //// Parse() ///////////////////////////////////////////////////////// -bool LocalizationXMLFile::Parse(const plString & fileName) +bool LocalizationXMLFile::Parse(const plString& fileName) { fFilename = fileName; @@ -390,7 +385,7 @@ bool LocalizationXMLFile::Parse(const plString & fileName) hsStream *xmlStream = plEncryptedStream::OpenEncryptedFile(fileName.c_str()); if (!xmlStream) { - pfLocalizationDataMgr::GetLog()->AddLineF("ERROR: Can't open file stream for %S", fileName.c_str()); + pfLocalizationDataMgr::GetLog()->AddLineF("ERROR: Can't open file stream for %s", fileName.c_str()); return false; } @@ -424,7 +419,7 @@ bool LocalizationXMLFile::Parse(const plString & fileName) void LocalizationXMLFile::AddError(const plString& errorText) { - pfLocalizationDataMgr::GetLog()->AddLineF("ERROR (line %d): %S", + pfLocalizationDataMgr::GetLog()->AddLineF("ERROR (line %d): %s", XML_GetCurrentLineNumber(fParser), errorText.c_str()); fSkipDepth = fTagStack.size(); // skip this block fWeExploded = true; @@ -443,7 +438,6 @@ class LocalizationDatabase { protected: plString fDirectory; // the directory we're supposed to parse - plString fErrorString; // total sum of all errors encountered (also has warnings and status messages) std::vector fFiles; // the various XML files in that directory @@ -480,7 +474,7 @@ LocalizationXMLFile::element LocalizationDatabase::IMergeElementData(Localizatio { if (firstElement.find(curTranslation->first) != firstElement.end()) { - pfLocalizationDataMgr::GetLog()->AddLineF("Duplicate %S translation for %S found in file %S Ignoring second translation", + pfLocalizationDataMgr::GetLog()->AddLineF("Duplicate %s translation for %s found in file %s. Ignoring second translation.", curTranslation->first.c_str(), path.c_str(), fileName.c_str()); } else @@ -502,7 +496,8 @@ LocalizationXMLFile::set LocalizationDatabase::IMergeSetData(LocalizationXMLFile if (firstSet.find(curElement->first) == firstSet.end()) firstSet[curElement->first] = curElement->second; else // merge the element in - firstSet[curElement->first] = IMergeElementData(firstSet[curElement->first], curElement->second, fileName, path + "." + curElement->first); + firstSet[curElement->first] = IMergeElementData(firstSet[curElement->first], curElement->second, fileName, + plString::Format("%s.%s", path.c_str(), curElement->first.c_str())); } return firstSet; @@ -520,7 +515,8 @@ LocalizationXMLFile::age LocalizationDatabase::IMergeAgeData(LocalizationXMLFile if (firstAge.find(curSet->first) == firstAge.end()) firstAge[curSet->first] = curSet->second; else // merge the data in - firstAge[curSet->first] = IMergeSetData(firstAge[curSet->first], curSet->second, fileName, path + "." + curSet->first); + firstAge[curSet->first] = IMergeSetData(firstAge[curSet->first], curSet->second, fileName, + plString::Format("%s.%s", path.c_str(), curSet->first.c_str())); } return firstAge; @@ -579,7 +575,7 @@ void LocalizationDatabase::IVerifyElement(const plString &ageName, const plStrin if (!languageExists) { - pfLocalizationDataMgr::GetLog()->AddLineF("ERROR: The language %S used by %S.%S.%S is not supported, discarding translation", + pfLocalizationDataMgr::GetLog()->AddLineF("ERROR: The language %s used by %s.%s.%s is not supported. Discarding translation.", curTranslation->first.c_str(), ageName.c_str(), setName.c_str(), elementName.c_str()); curTranslation = theElement.erase(curTranslation); } @@ -591,7 +587,7 @@ void LocalizationDatabase::IVerifyElement(const plString &ageName, const plStrin { if (theElement.find(languageNames[i]) == theElement.end()) { - pfLocalizationDataMgr::GetLog()->AddLineF("WARNING: Language %S is missing from the translations in element %S.%S.%S, you'll want to get translations for that!", + pfLocalizationDataMgr::GetLog()->AddLineF("WARNING: Language %s is missing from the translations in element %s.%s.%s. You'll want to get translations for that!", languageNames[i].c_str(), ageName.c_str(), setName.c_str(), elementName.c_str()); } } @@ -611,7 +607,7 @@ void LocalizationDatabase::IVerifySet(const plString &ageName, const plString &s // Check that we at least have a default language translation for fallback if (curElement->second.find(defaultLanguage) == curElement->second.end()) { - pfLocalizationDataMgr::GetLog()->AddLineF("ERROR: Default language %S is missing from the translations in element %S.%S.%S, deleting element", + pfLocalizationDataMgr::GetLog()->AddLineF("ERROR: Default language %s is missing from the translations in element %s.%s.%s. Deleting element.", defaultLanguage.c_str(), ageName.c_str(), setName.c_str(), curElement->first.c_str()); curElement = theSet.erase(curElement); } @@ -679,20 +675,13 @@ void LocalizationDatabase::Parse(const plString & directory) template void pfLocalizationDataMgr::pf3PartMap::ISplitString(plString key, plString &age, plString &set, plString &name) { - int periodLoc = key.Find("."); - age = key.Substr(0, periodLoc); - if (periodLoc >= key.GetSize()) { - return; // don't get set or name if there isn't any period - } - - key = key.Substr(periodLoc + 1, key.GetSize()); - periodLoc = key.Find("."); - set = key.Substr(0, periodLoc); - if (periodLoc >= key.GetSize()) { - return; // don't get name if there isn't another period - } - - name = key.Substr(periodLoc + 1, key.GetSize()); + std::vector tokens = key.Tokenize("."); + if (tokens.size() >= 1) + age = tokens[0]; + if (tokens.size() >= 2) + set = tokens[1]; + if (tokens.size() >= 3) + name = tokens[2]; } //// exists() //////////////////////////////////////////////////////// @@ -702,7 +691,7 @@ bool pfLocalizationDataMgr::pf3PartMap::exists(const plString & key) { plString age, set, name; ISplitString(key, age, set, name); - if (age == "" || set == "" || name == "") // if any are missing, it's invalid, so we don't have it + if (age.IsEmpty() || set.IsEmpty() || name.IsEmpty()) // if any are missing, it's invalid, so we don't have it return false; // now check individually @@ -724,7 +713,7 @@ bool pfLocalizationDataMgr::pf3PartMap::setExists(const plString & key) { plString age, set, name; ISplitString(key, age, set, name); - if (age == "" || set == "") // if any are missing, it's invalid, so we don't have it (ignoring name) + if (age.IsEmpty() || set.IsEmpty()) // if any are missing, it's invalid, so we don't have it (ignoring name) return false; // now check individually @@ -744,7 +733,7 @@ void pfLocalizationDataMgr::pf3PartMap::erase(const plString & key) { plString age, set, name; ISplitString(key, age, set, name); - if (age == "" || set == "" || name == "") // if any are missing, it's invalid, so we don't delete it + if (age.IsEmpty() || set.IsEmpty() || name.IsEmpty()) // if any are missing, it's invalid, so we don't delete it return; // now check individually @@ -863,8 +852,7 @@ pfLocalizationDataMgr::localizedElement pfLocalizationDataMgr::ICreateLocalizedE for (int curLocale = 0; curLocale <= numLocales; curLocale++) { - plString name = plLocalization::GetLanguageName((plLocalization::Language)curLocale); - retVal[name] = ""; + retVal[plLocalization::GetLanguageName((plLocalization::Language)curLocale)] = ""; } return retVal; @@ -874,8 +862,7 @@ pfLocalizationDataMgr::localizedElement pfLocalizationDataMgr::ICreateLocalizedE plString pfLocalizationDataMgr::IGetCurrentLanguageName() { - plString retVal = plLocalization::GetLanguageName(plLocalization::GetLanguage()); - return retVal; + return plLocalization::GetLanguageName(plLocalization::GetLanguage()); } //// IGetAllLanguageNames //////////////////////////////////////////// @@ -909,7 +896,7 @@ void pfLocalizationDataMgr::IConvertElement(LocElementInfo *elementInfo, const p if (numArgs == -1) // just started numArgs = argCount; else if (argCount != numArgs) - fLog->AddLineF("WARNING: Argument number mismatch in element %S for %S", curPath.c_str(), curTranslation->first.c_str()); + fLog->AddLineF("WARNING: Argument number mismatch in element %s for %s", curPath.c_str(), curTranslation->first.c_str()); } fLocalizedElements[curPath] = newElement; @@ -925,7 +912,7 @@ void pfLocalizationDataMgr::IConvertSet(LocSetInfo *setInfo, const plString & cu LocElementInfo elementInfo; elementInfo.fElement = curElement->second; - IConvertElement(&elementInfo, plString::Format("%S.%S", curPath.c_str(), curElement->first.c_str())); + IConvertElement(&elementInfo, plString::Format("%s.%s", curPath.c_str(), curElement->first.c_str())); } } @@ -939,7 +926,7 @@ void pfLocalizationDataMgr::IConvertAge(LocAgeInfo *ageInfo, const plString & cu LocSetInfo setInfo; setInfo.fSet = curSet->second; - IConvertSet(&setInfo, plString::Format("%S.%S", curPath.c_str(), curSet->first.c_str())); + IConvertSet(&setInfo, plString::Format("%s.%s", curPath.c_str(), curSet->first.c_str())); } } @@ -954,26 +941,26 @@ void pfLocalizationDataMgr::IWriteText(const plString & filename, const plString plStringStream fileData; fileData << "\n"; // stores the xml we are going to write to the file (UTF-16 format) fileData << "\n"; - fileData << plString::Format("\t\n", ageName.c_str()); + fileData << plString::Format("\t\n", ageName.c_str()); std::vector setNames = GetSetList(ageName); for (int curSet = 0; curSet < setNames.size(); curSet++) { setEmpty = true; // so far, this set is empty plStringStream setCode; - setCode << plString::Format("\t\t\n", setNames[curSet].c_str()); + setCode << plString::Format("\t\t\n", setNames[curSet].c_str()); std::vector elementNames = GetElementList(ageName, setNames[curSet]); for (int curElement = 0; curElement < elementNames.size(); curElement++) { - setCode << plString::Format("\t\t\t\n", elementNames[curElement].c_str()); - plString key = plString::Format("%S.%S.%S", ageName.c_str(), setNames[curSet].c_str(), elementNames[curElement].c_str()); + setCode << plString::Format("\t\t\t\n", elementNames[curElement].c_str()); + plString key = plString::Format("%s.%s.%s", ageName.c_str(), setNames[curSet].c_str(), elementNames[curElement].c_str()); if (fLocalizedElements[key].find(languageName) != fLocalizedElements[key].end()) { weWroteData = true; setEmpty = false; - setCode << plString::Format("\t\t\t\t", languageName.c_str()); + setCode << plString::Format("\t\t\t\t", languageName.c_str()); setCode << fLocalizedElements[key][languageName].ToXML(); setCode << "\n"; } @@ -1044,7 +1031,7 @@ void pfLocalizationDataMgr::SetupData() // and now we read all the data out of the database and convert it to our native formats - // transfer subtitle data + // transfer localization data LocalizationXMLFile::ageMap data = fDatabase->GetData(); LocalizationXMLFile::ageMap::iterator curAge; for (curAge = data.begin(); curAge != data.end(); curAge++) @@ -1099,7 +1086,7 @@ pfLocalizedString pfLocalizationDataMgr::GetSpecificElement(const plString & nam std::vector pfLocalizationDataMgr::GetLanguages(const plString & ageName, const plString & setName, const plString & elementName) { std::vector retVal; - plString key = plString::Format("%S.%S.%S", ageName.c_str(), setName.c_str(), elementName.c_str()); + plString key = plString::Format("%s.%s.%s", ageName.c_str(), setName.c_str(), elementName.c_str()); if (fLocalizedElements.exists(key)) { // age, set, and element exists @@ -1119,26 +1106,18 @@ std::vector pfLocalizationDataMgr::GetLanguages(const plString & ageNa plString pfLocalizationDataMgr::GetElementXMLData(const plString & name, const plString & languageName) { - plString retVal = ""; - if (fLocalizedElements.exists(name)) - { - if (fLocalizedElements[name].find(languageName) != fLocalizedElements[name].end()) - retVal = fLocalizedElements[name][languageName].ToXML(); - } - return retVal; + if (fLocalizedElements.exists(name) && (fLocalizedElements[name].find(languageName) != fLocalizedElements[name].end())) + return fLocalizedElements[name][languageName].ToXML(); + return ""; } //// GetElementPlainTextData ///////////////////////////////////////// plString pfLocalizationDataMgr::GetElementPlainTextData(const plString & name, const plString & languageName) { - plString retVal = ""; - if (fLocalizedElements.exists(name)) - { - if (fLocalizedElements[name].find(languageName) != fLocalizedElements[name].end()) - retVal = fLocalizedElements[name][languageName]; - } - return retVal; + if (fLocalizedElements.exists(name) && (fLocalizedElements[name].find(languageName) != fLocalizedElements[name].end())) + return fLocalizedElements[name][languageName]; + return ""; } //// SetElementXMLData /////////////////////////////////////////////// @@ -1217,14 +1196,13 @@ bool pfLocalizationDataMgr::DeleteElement(const plString & name) void pfLocalizationDataMgr::WriteDatabaseToDisk(const plString & path) { - // first, write the styles and panel settings to styles.sub std::vector ageNames = GetAgeList(); std::vector languageNames = IGetAllLanguageNames(); for (int curAge = 0; curAge < ageNames.size(); curAge++) { for (int curLanguage = 0; curLanguage < languageNames.size(); curLanguage++) { - IWriteText(plString::Format("%S/%S%S.loc", path, ageNames[curAge].c_str(), languageNames[curLanguage].c_str()), ageNames[curAge], languageNames[curLanguage]); + IWriteText(plString::Format("%s/%s%s.loc", path, ageNames[curAge].c_str(), languageNames[curLanguage].c_str()), ageNames[curAge], languageNames[curLanguage]); } } } @@ -1241,19 +1219,19 @@ void pfLocalizationDataMgr::OutputTreeToLog() for (std::vector::iterator i = ages.begin(); i != ages.end(); ++i) { plString age = *i; - fLog->AddLineF("\t%S", age.c_str()); + fLog->AddLineF("\t%s", age.c_str()); std::vector sets = GetSetList(age); for (std::vector::iterator j = sets.begin(); j != sets.end(); ++j) { plString set = (*j); - fLog->AddLineF("\t\t%S", set.c_str()); + fLog->AddLineF("\t\t%s", set.c_str()); std::vector names = GetElementList(age, set); for (std::vector::iterator k = names.begin(); k != names.end(); ++k) { plString name = (*k); - fLog->AddLineF("\t\t\t%S", name.c_str()); + fLog->AddLineF("\t\t\t%s", name.c_str()); } } } diff --git a/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizationMgr.cpp b/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizationMgr.cpp index 3d47e5fe..e6de8c66 100644 --- a/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizationMgr.cpp +++ b/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizationMgr.cpp @@ -73,13 +73,13 @@ pfLocalizationMgr::~pfLocalizationMgr() //// Initialize ////////////////////////////////////////////////////// -void pfLocalizationMgr::Initialize(const std::string & dataPath) +void pfLocalizationMgr::Initialize(const plString & dataPath) { if (fInstance) return; fInstance = new pfLocalizationMgr(); - pfLocalizationDataMgr::Initialize(dataPath.c_str()); // set up the data manager + pfLocalizationDataMgr::Initialize(dataPath); // set up the data manager } //// Shutdown //////////////////////////////////////////////////////// diff --git a/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizationMgr.h b/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizationMgr.h index e8df4234..7fc99964 100644 --- a/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizationMgr.h +++ b/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizationMgr.h @@ -60,7 +60,7 @@ protected: public: virtual ~pfLocalizationMgr(); - static void Initialize(const std::string & dataPath); + static void Initialize(const plString & dataPath); static void Shutdown(); static pfLocalizationMgr &Instance(void) {return *fInstance;} static bool InstanceValid(void) {return fInstance != nil;} diff --git a/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizedString.cpp b/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizedString.cpp index 404d94e4..510735fe 100644 --- a/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizedString.cpp +++ b/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizedString.cpp @@ -51,10 +51,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com #include "pfLocalizedString.h" -// MinGW sucks -#if defined(_WIN32) && !defined(_MSC_VER) -# define swprintf _snwprintf -#endif ////////////////////////////////////////////////////////////////////// //// pfLocalizedString functions ///////////////////////////////////// @@ -63,87 +59,89 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com //// Constructors //////////////////////////////////////////////////// pfLocalizedString::pfLocalizedString(const plString & plainText) + : fNumArguments(0) { - fNumArguments = 0; IConvertFromPlainText(plainText); } -//// IConvertFromPlainText /////////////////////////////////////////// +//// IParameterize /////////////////////////////////////////////////// -void pfLocalizedString::IConvertFromPlainText(const plString & plainText) +void pfLocalizedString::IParameterize(const plString & inString) { textBlock curTextBlock; - fText.clear(); - fPlainTextRep = plainText; - fNumArguments = 0; // reset the argument count + fNumArguments = 0; // Reset the argument count. + fText.clear(); // Reset the text blocks. + + plString remainder = inString; + plStringStream newText; int curParameter = 0; + int nextToken = -1; - plString::iterator iter = plainText.GetIterator(); - while (!iter.AtEnd()) + while (!remainder.IsEmpty()) { - wchar_t curChar = *iter; - bool isLastChar = iter.AtEnd(); - switch (curChar) - { - case L'\\': - if (!isLastChar) - { - // we need to see the next character - iter++; - wchar_t nextChar = *iter; - if ((nextChar == L'%')||(nextChar == L'\\')) - { - // we recognize it as an escaped character, so add it to the text - curTextBlock.fText += plString::FromWchar((const wchar_t *)(nextChar)); - } - // otherwise we don't recognize it and it will be skipped - } - // if it's the last char, just drop it - break; - case L'%': - if (!isLastChar) - { - // we need to grab the trailing s character - std::wstring::size_type endArgPos = plainText.find(L"s", curIndex); - if (endArgPos != std::wstring::npos) // make sure the s exists - { - if (endArgPos == (curIndex + 1)) // no number specifier - { - fText.push_back(curTextBlock); + // Check if we have any params. + nextToken = remainder.Find("%"); + if (nextToken != -1) + { + // Check it's not escaped. + if ((nextToken > 0) && (remainder.CharAt(nextToken-1) != '\\')) + { + // Check if it has an end. + int endToken = remainder.Substr(nextToken).Find("s"); + if (endToken != -1) + { + // Store existing block. + newText << remainder; + curTextBlock.fText = newText.GetString().Replace("\\\\", "\\"); + fText.push_back(curTextBlock); + + if (endToken == nextToken + 1) + { + // Store non-indexed param block. curTextBlock.fIsParam = true; - curTextBlock.fParamIndex = curParameter; - curParameter++; - curTextBlock.fText = L""; - fText.push_back(curTextBlock); - curTextBlock.fIsParam = false; - curTextBlock.fParamIndex = 0; - } - else // number specified - { + curTextBlock.fParamIndex = curParameter++; + curTextBlock.fText = ""; fText.push_back(curTextBlock); + } + else + { + // Store indexed param block. curTextBlock.fIsParam = true; - curTextBlock.fText = L""; - - std::wstring number = plainText.substr(curIndex + 1, (endArgPos - (curIndex + 1))); - curTextBlock.fParamIndex = (uint8_t)wcstol(number.c_str(), NULL, 10) - 1; // args are 1-based, vectors are 0-based + curTextBlock.fParamIndex = remainder.Substr(nextToken, endToken-1).ToInt(10) - 1; // args start at 1 + curTextBlock.fText = ""; fText.push_back(curTextBlock); - - curTextBlock.fIsParam = false; - curTextBlock.fParamIndex = 0; - } - fNumArguments++; // increment our argument count - curIndex = endArgPos; // update our position - } - // if s didn't exist, we just skip this % sign - } - // if it was the last char, we just skip this % sign - break; - default: - curTextBlock.fText += curChar; - break; - } + } + curTextBlock.fIsParam = false; + curTextBlock.fParamIndex = 0; + fNumArguments++; + + // Continue using the remaining string. + remainder = remainder.Substr(endToken+1); + } + } + else + { + // Copy the text up to the escape character, skip it, and continue. + newText << remainder.Substr(0, nextToken - 1) << '%'; + remainder = remainder.Substr(nextToken + 1); + } + } + else + { + // We're done. Copy the remaining text and finish. + newText << remainder; + remainder = ""; + curTextBlock.fText = newText.GetString().Replace("\\\\", "\\"); + fText.push_back(curTextBlock); + } } - fText.push_back(curTextBlock); +} + +//// IConvertFromPlainText /////////////////////////////////////////// + +void pfLocalizedString::IConvertFromPlainText(const plString & plainText) +{ + IParameterize(plainText); IUpdateXML(); } @@ -152,7 +150,7 @@ void pfLocalizedString::IConvertFromPlainText(const plString & plainText) void pfLocalizedString::IUpdatePlainText() { - fPlainTextRep = ""; + plStringStream ss; for (std::vector::size_type curIndex = 0; curIndex < fText.size(); curIndex++) { @@ -160,133 +158,50 @@ void pfLocalizedString::IUpdatePlainText() if (curTextBlock.fIsParam) { - fPlainTextRep += plString::Format("%%%ds", curTextBlock.fParamIndex + 1); + // Fill in parameter value. + ss << plString::Format("%%%ds", curTextBlock.fParamIndex + 1); } else { - // otherwise, we need to copy all the text over, making sure that % and \ are properly escaped - for (plString::iterator iter = curTextBlock.fText.GetIterator(); !iter.AtEnd(); iter++) - { - if (((*iter) == L'\\') || ((*iter) == L'%')) - fPlainTextRep += "\\"; - fPlainTextRep += plString::FromWchar((const wchar_t *)(*iter)); - } + // Escape special characters. + ss << curTextBlock.fText.Replace("\\","\\\\").Replace("%","\\%"); } } + fPlainTextRep = ss.GetString(); } //// IConvertFromXML ///////////////////////////////////////////////// void pfLocalizedString::IConvertFromXML(const plString & xml) { - textBlock curTextBlock; - fText.clear(); - fNumArguments = 0; // reset the argument counter - int curParameter = 0; - - for (std::wstring::size_type curIndex = 0; curIndex < xml.length(); curIndex++) - { - wchar_t curChar = xml[curIndex]; - bool isLastChar = (curIndex == (xml.length() - 1)); - switch (curChar) - { // expat handles the > < and so on stuff for us - case L'\\': // but we want to be able to escape the % sign and the \ character - if (!isLastChar) - { - // we need to see the next character - curIndex++; - wchar_t nextChar = xml[curIndex]; - if ((nextChar == L'%')||(nextChar == L'\\')) - { - // we recognize it as an escaped character, so add it to the text - curTextBlock.fText += nextChar; - } - // otherwise we don't recognize it and it will be skipped - } - // if it's the last char, just drop it - break; - case L'%': - if (!isLastChar) - { - // we need to grab the trailing s character - std::wstring::size_type endArgPos = xml.find(L"s", curIndex); - if (endArgPos != std::wstring::npos) // make sure the s exists - { - if (endArgPos == (curIndex + 1)) // no number specifier - { - fText.push_back(curTextBlock); - curTextBlock.fIsParam = true; - curTextBlock.fParamIndex = curParameter; - curParameter++; - curTextBlock.fText = L""; - fText.push_back(curTextBlock); - curTextBlock.fIsParam = false; - curTextBlock.fParamIndex = 0; - } - else // number specified - { - fText.push_back(curTextBlock); - curTextBlock.fIsParam = true; - curTextBlock.fText = L""; - - std::wstring number = xml.substr(curIndex + 1, (endArgPos - (curIndex + 1))); - curTextBlock.fParamIndex = (uint8_t)wcstol(number.c_str(), nil, 10) - 1; // args are 1-based, vectors are 0-based - fText.push_back(curTextBlock); - - curTextBlock.fIsParam = false; - curTextBlock.fParamIndex = 0; - } - fNumArguments++; // increment the number of arguments - curIndex = endArgPos; // update our position - } - // if s didn't exist, we just skip this % sign - } - // if it was the last char, we just skip this % sign - break; - default: - curTextBlock.fText += curChar; - break; - } - } - fText.push_back(curTextBlock); + IParameterize(xml); IUpdatePlainText(); - IUpdateXML(); // we don't really get pure xml from the parser (since it auto translates all the &x; stuff) + IUpdateXML(); } //// IUpdateXML ////////////////////////////////////////////////////// void pfLocalizedString::IUpdateXML() { - fXMLRep = ""; + plStringStream ss; for (std::vector::size_type curIndex = 0; curIndex < fText.size(); curIndex++) { textBlock curTextBlock = fText[curIndex]; if (curTextBlock.fIsParam) { + // Fill in parameter value. plString paramStr = plString::Format("%%%ds", curTextBlock.fParamIndex + 1); - fXMLRep += paramStr; + ss << paramStr; } else { - // otherwise, we need to copy all the text over, making sure that %, &, <, and > are properly converted - for (plString::iterator iter = curTextBlock.fText.GetIterator(); !iter.AtEnd(); iter++) - { - UniChar curChar = *iter; - if (curChar == L'%') - fXMLRep += "\\%"; - else if (curChar == L'&') - fXMLRep += "&"; - else if (curChar == L'<') - fXMLRep += "<"; - else if (curChar == L'>') - fXMLRep += ">"; - else - fXMLRep += plString::FromWchar((const wchar_t *)curChar); - } + // Encode XML entities. + ss << curTextBlock.fText.Replace("%", "\\%").Replace("&", "&").Replace("<", "<").Replace(">", ">"); } } + fXMLRep = ss.GetString(); } //// FromXML ///////////////////////////////////////////////////////// @@ -300,32 +215,32 @@ void pfLocalizedString::FromXML(const plString & xml) bool pfLocalizedString::operator<(pfLocalizedString &obj) { - return (fPlainTextRep < obj.fPlainTextRep); + return (fPlainTextRep.Compare(obj.fPlainTextRep) < 0); } bool pfLocalizedString::operator>(pfLocalizedString &obj) { - return (fPlainTextRep > obj.fPlainTextRep); + return (fPlainTextRep.Compare(obj.fPlainTextRep) > 0); } bool pfLocalizedString::operator==(pfLocalizedString &obj) { - return (fPlainTextRep == obj.fPlainTextRep); + return (fPlainTextRep.Compare(obj.fPlainTextRep) == 0); } bool pfLocalizedString::operator<=(pfLocalizedString &obj) { - return (fPlainTextRep <= obj.fPlainTextRep); + return (fPlainTextRep.Compare(obj.fPlainTextRep) <= 0); } bool pfLocalizedString::operator>=(pfLocalizedString &obj) { - return (fPlainTextRep >= obj.fPlainTextRep); + return (fPlainTextRep.Compare(obj.fPlainTextRep) >= 0); } bool pfLocalizedString::operator!=(pfLocalizedString &obj) { - return (fPlainTextRep != obj.fPlainTextRep); + return (fPlainTextRep.Compare(obj.fPlainTextRep) != 0); } pfLocalizedString pfLocalizedString::operator+(pfLocalizedString &obj) @@ -350,17 +265,17 @@ pfLocalizedString &pfLocalizedString::operator=(const plString & plainText) plString pfLocalizedString::operator%(const std::vector & arguments) { - plString retVal = ""; + plStringStream ss; for (std::vector::size_type curIndex = 0; curIndex < fText.size(); curIndex++) { if (fText[curIndex].fIsParam) { int curParam = fText[curIndex].fParamIndex; if (curParam < arguments.size()) - retVal += arguments[curParam]; + ss << arguments[curParam]; } else - retVal += fText[curIndex].fText; + ss << fText[curIndex].fText; } - return retVal; + return ss.GetString(); } diff --git a/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizedString.h b/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizedString.h index 58350353..e8737e7f 100644 --- a/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizedString.h +++ b/Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizedString.h @@ -77,6 +77,7 @@ protected: plString fPlainTextRep; // the plain text representation of this string uint16_t fNumArguments; // number of arguments this string has + void IParameterize(const plString & inString); void IConvertFromPlainText(const plString & plainText); void IUpdatePlainText(); // from the internal representation void IConvertFromXML(const plString & xml); diff --git a/Sources/Plasma/FeatureLib/pfPython/cyMisc.cpp b/Sources/Plasma/FeatureLib/pfPython/cyMisc.cpp index ad39bd78..763aab23 100644 --- a/Sources/Plasma/FeatureLib/pfPython/cyMisc.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/cyMisc.cpp @@ -2725,11 +2725,11 @@ void cyMisc::ForceCursorShown() // properly replaced (the list is a list of unicode strings) Name // is in "Age.Set.Name" format // -std::wstring cyMisc::GetLocalizedString(std::wstring name, const std::vector & arguments) +plString cyMisc::GetLocalizedString(plString name, const std::vector & arguments) { if (pfLocalizationMgr::InstanceValid()) return pfLocalizationMgr::Instance().GetString(name, arguments); - return L""; + return ""; } void cyMisc::EnablePlanarReflections(bool enable) diff --git a/Sources/Plasma/FeatureLib/pfPython/cyMisc.h b/Sources/Plasma/FeatureLib/pfPython/cyMisc.h index a0d901f8..0b0d8454 100644 --- a/Sources/Plasma/FeatureLib/pfPython/cyMisc.h +++ b/Sources/Plasma/FeatureLib/pfPython/cyMisc.h @@ -922,7 +922,7 @@ public: // properly replaced (the list is a list of unicode strings) Name // is in "Age.Set.Name" format // - static std::wstring GetLocalizedString(std::wstring name, const std::vector & arguments); + static plString GetLocalizedString(plString name, const std::vector & arguments); static void EnablePlanarReflections(bool enable = true); static void SetGraphicsOptions(int Width, int Height, int ColorDepth, bool Windowed, int NumAASamples, int MaxAnisotropicSamples, bool VSync); diff --git a/Sources/Plasma/FeatureLib/pfPython/cyMiscGlue.cpp b/Sources/Plasma/FeatureLib/pfPython/cyMiscGlue.cpp index 94a75835..d512c676 100644 --- a/Sources/Plasma/FeatureLib/pfPython/cyMiscGlue.cpp +++ b/Sources/Plasma/FeatureLib/pfPython/cyMiscGlue.cpp @@ -409,8 +409,8 @@ PYTHON_GLOBAL_METHOD_DEFINITION(PtGetLocalizedString, args, "Params: name, argum PyErr_SetString(PyExc_TypeError, "PtGetLocalizedString expects a unicode string and a list of unicode strings"); PYTHON_RETURN_ERROR; } - std::wstring name; - std::vector argList; + plString name; + std::vector argList; // convert name from a string or unicode string if (PyUnicode_Check(nameObj)) @@ -419,14 +419,14 @@ PYTHON_GLOBAL_METHOD_DEFINITION(PtGetLocalizedString, args, "Params: name, argum wchar_t* buffer = new wchar_t[len + 1]; PyUnicode_AsWideChar((PyUnicodeObject*)nameObj, buffer, len); buffer[len] = L'\0'; - name = buffer; + name = plString::FromWchar(buffer); delete [] buffer; } else if (PyString_Check(nameObj)) { char* temp = PyString_AsString(nameObj); wchar_t* wTemp = hsStringToWString(temp); - name = wTemp; + name = plString::FromWchar(wTemp); delete [] wTemp; } else @@ -448,23 +448,23 @@ PYTHON_GLOBAL_METHOD_DEFINITION(PtGetLocalizedString, args, "Params: name, argum for (int curItem = 0; curItem < len; curItem++) { PyObject* item = PyList_GetItem(argObj, curItem); - std::wstring arg = L"INVALID ARG"; + plString arg = "INVALID ARG"; if (item == Py_None) // none is allowed, but treated as a blank string - arg = L""; + arg = ""; else if (PyUnicode_Check(item)) { int strLen = PyUnicode_GetSize(item); wchar_t* buffer = new wchar_t[strLen + 1]; PyUnicode_AsWideChar((PyUnicodeObject*)item, buffer, strLen); buffer[strLen] = L'\0'; - arg = buffer; + arg = plString::FromWchar(buffer); delete [] buffer; } else if (PyString_Check(item)) { char* temp = PyString_AsString(item); wchar_t* wTemp = hsStringToWString(temp); - arg = wTemp; + arg = plString::FromWchar(wTemp); delete [] wTemp; } // everything else won't throw an error, but will show up as INVALID ARG in the string @@ -472,8 +472,8 @@ PYTHON_GLOBAL_METHOD_DEFINITION(PtGetLocalizedString, args, "Params: name, argum } } - std::wstring retVal = cyMisc::GetLocalizedString(name, argList); - return PyUnicode_FromWideChar(retVal.c_str(), retVal.length()); + plString retVal = cyMisc::GetLocalizedString(name, argList); + return PyUnicode_FromWideChar(retVal.ToWchar(), retVal.GetSize()); } PYTHON_GLOBAL_METHOD_DEFINITION(PtDumpLogs, args, "Params: folder\nDumps all current log files to the specified folder (a sub-folder to the log folder)")