Browse Source

Fix substring indexing and whitespace.

Fixes an off-by-one and off-by-initial-offset error,
not clearing the stream between loops,
and a few other edge conditions.
Joseph Davies 12 years ago
parent
commit
0efcebb2e9
  1. 91
      Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizedString.cpp

91
Sources/Plasma/FeatureLib/pfLocalizationMgr/pfLocalizedString.cpp

@ -69,8 +69,8 @@ pfLocalizedString::pfLocalizedString(const plString & plainText)
void pfLocalizedString::IParameterize(const plString & inString) void pfLocalizedString::IParameterize(const plString & inString)
{ {
textBlock curTextBlock; textBlock curTextBlock;
fNumArguments = 0; // Reset the argument count. fNumArguments = 0; // Reset the argument count.
fText.clear(); // Reset the text blocks. fText.clear(); // Reset the text blocks.
plString remainder = inString; plString remainder = inString;
plStringStream newText; plStringStream newText;
@ -79,61 +79,77 @@ void pfLocalizedString::IParameterize(const plString & inString)
while (!remainder.IsEmpty()) while (!remainder.IsEmpty())
{ {
// Check if we have any params. // Check if we have any params.
nextToken = remainder.Find("%"); nextToken = remainder.Find("%");
if (nextToken != -1) if (nextToken != -1)
{ {
// Check it's not escaped. // Check it's not escaped.
if ((nextToken > 0) && (remainder.CharAt(nextToken-1) != '\\')) if ((nextToken == 0) || ((nextToken > 0) && (remainder.CharAt(nextToken-1) != '\\')))
{ {
// Check if it has an end. // Check if it has an end (ignoring any terminators we need to cross a space to find).
int endToken = remainder.Substr(nextToken).Find("s"); int endToken = remainder.Substr(nextToken).Find("s");
if (endToken != -1) if ((endToken != -1) && (remainder.Substr(nextToken, endToken).Find(" ") == -1))
{ {
// Store existing block. // Store existing block if it contains anything.
newText << remainder; newText << remainder.Substr(0, nextToken);
curTextBlock.fText = newText.GetString().Replace("\\\\", "\\"); curTextBlock.fText = newText.GetString().Replace("\\\\", "\\");
fText.push_back(curTextBlock); if (!curTextBlock.fText.IsEmpty())
{
fText.push_back(curTextBlock);
newText.Truncate();
}
if (endToken == nextToken + 1) if (endToken == nextToken + 1)
{ {
// Store non-indexed param block. // Store non-indexed param block.
curTextBlock.fIsParam = true; curTextBlock.fIsParam = true;
curTextBlock.fParamIndex = curParameter++; curTextBlock.fParamIndex = curParameter++;
curTextBlock.fText = ""; curTextBlock.fText = "";
fText.push_back(curTextBlock); fText.push_back(curTextBlock);
} }
else else
{ {
// Store indexed param block. // Store indexed param block.
curTextBlock.fIsParam = true; curTextBlock.fIsParam = true;
curTextBlock.fParamIndex = remainder.Substr(nextToken, endToken-1).ToInt(10) - 1; // args start at 1 curTextBlock.fParamIndex = remainder.Substr(nextToken + 1, endToken - 1).ToInt(10) - 1; // args start at 1
curTextBlock.fText = ""; curTextBlock.fText = "";
fText.push_back(curTextBlock); fText.push_back(curTextBlock);
} }
curTextBlock.fIsParam = false; curTextBlock.fIsParam = false;
curTextBlock.fParamIndex = 0; curTextBlock.fParamIndex = 0;
fNumArguments++; fNumArguments++;
// Continue using the remaining string. // Continue, using the remaining string.
remainder = remainder.Substr(endToken+1); remainder = remainder.Substr(nextToken + endToken + 1);
} }
} else
else {
{ // We have an unescaped but unterminated %.
// For now, let's just pretend it was escaped;
// This way they'll show up visibly in-game and will be reported.
newText << "%";
remainder = remainder.Substr(nextToken + 1);
}
}
else
{
// Copy the text up to the escape character, skip it, and continue. // Copy the text up to the escape character, skip it, and continue.
newText << remainder.Substr(0, nextToken - 1) << '%'; newText << remainder.Substr(0, nextToken - 1) << '%';
remainder = remainder.Substr(nextToken + 1); remainder = remainder.Substr(nextToken + 1);
} }
} }
else else
{ {
// We're done. Copy the remaining text and finish. // We're done. Copy the remaining text and finish.
newText << remainder; newText << remainder;
remainder = ""; remainder = "";
curTextBlock.fText = newText.GetString().Replace("\\\\", "\\"); curTextBlock.fText = newText.GetString().Replace("\\\\", "\\");
fText.push_back(curTextBlock); if (!curTextBlock.fText.IsEmpty())
} {
fText.push_back(curTextBlock);
newText.Truncate();
}
}
} }
} }
@ -159,7 +175,7 @@ void pfLocalizedString::IUpdatePlainText()
if (curTextBlock.fIsParam) if (curTextBlock.fIsParam)
{ {
// Fill in parameter value. // Fill in parameter value.
ss << plString::Format("%%%ds", curTextBlock.fParamIndex + 1); ss << "%%" << curTextBlock.fParamIndex + 1 << "s";
} }
else else
{ {
@ -192,8 +208,7 @@ void pfLocalizedString::IUpdateXML()
if (curTextBlock.fIsParam) if (curTextBlock.fIsParam)
{ {
// Fill in parameter value. // Fill in parameter value.
plString paramStr = plString::Format("%%%ds", curTextBlock.fParamIndex + 1); ss << "%%" << curTextBlock.fParamIndex + 1 << "s";
ss << paramStr;
} }
else else
{ {

Loading…
Cancel
Save