forked from teamnwah/openmw-tes3coop
Improve format specifiers for message boxes
This commit is contained in:
parent
6f376bd499
commit
f6f3f71db5
6 changed files with 207 additions and 73 deletions
|
@ -85,7 +85,7 @@ add_component_dir (esmterrain
|
|||
)
|
||||
|
||||
add_component_dir (misc
|
||||
utf8stream stringops resourcehelpers rng
|
||||
utf8stream stringops resourcehelpers rng messageformatparser
|
||||
)
|
||||
|
||||
IF(NOT WIN32 AND NOT APPLE)
|
||||
|
|
|
@ -140,30 +140,9 @@ namespace Compiler
|
|||
|
||||
if (mState==MessageState || mState==MessageCommaState)
|
||||
{
|
||||
std::string arguments;
|
||||
|
||||
for (std::size_t i=0; i<name.size(); ++i)
|
||||
{
|
||||
if (name[i]=='%')
|
||||
{
|
||||
++i;
|
||||
if (i<name.size())
|
||||
{
|
||||
if (name[i]=='G' || name[i]=='g')
|
||||
{
|
||||
arguments += "l";
|
||||
}
|
||||
else if (name[i]=='S' || name[i]=='s')
|
||||
{
|
||||
arguments += 'S';
|
||||
}
|
||||
else if (name[i]=='.' || name[i]=='f')
|
||||
{
|
||||
arguments += 'f';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
GetArgumentsFromMessageFormat processor;
|
||||
processor.process(name);
|
||||
std::string arguments = processor.getArguments();
|
||||
|
||||
if (!arguments.empty())
|
||||
{
|
||||
|
@ -577,4 +556,23 @@ namespace Compiler
|
|||
mName.clear();
|
||||
mExplicit.clear();
|
||||
}
|
||||
|
||||
void GetArgumentsFromMessageFormat::visitedPlaceholder(Placeholder placeholder, char /*padding*/, int /*width*/, int /*precision*/)
|
||||
{
|
||||
switch (placeholder)
|
||||
{
|
||||
case StringPlaceholder:
|
||||
mArguments += 'S';
|
||||
break;
|
||||
case IntegerPlaceholder:
|
||||
mArguments += 'l';
|
||||
break;
|
||||
case FloatPlaceholder:
|
||||
mArguments += 'f';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
#define COMPILER_LINEPARSER_H_INCLUDED
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <components/interpreter/types.hpp>
|
||||
#include <components/misc/messageformatparser.hpp>
|
||||
|
||||
#include "parser.hpp"
|
||||
#include "exprparser.hpp"
|
||||
|
@ -74,6 +76,24 @@ namespace Compiler
|
|||
void reset();
|
||||
///< Reset parser to clean state.
|
||||
};
|
||||
|
||||
class GetArgumentsFromMessageFormat : public ::Misc::MessageFormatParser
|
||||
{
|
||||
private:
|
||||
std::string mArguments;
|
||||
|
||||
protected:
|
||||
virtual void visitedPlaceholder(Placeholder placeholder, char padding, int width, int precision);
|
||||
virtual void visitedCharacter(char c) {}
|
||||
|
||||
public:
|
||||
virtual void process(const std::string& message)
|
||||
{
|
||||
mArguments.clear();
|
||||
::Misc::MessageFormatParser::process(message);
|
||||
}
|
||||
std::string getArguments() const { return mArguments; }
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -13,67 +13,89 @@
|
|||
#include "defines.hpp"
|
||||
|
||||
#include <components/misc/rng.hpp>
|
||||
#include <components/misc/messageformatparser.hpp>
|
||||
|
||||
namespace Interpreter
|
||||
{
|
||||
inline std::string formatMessage (const std::string& message, Runtime& runtime)
|
||||
class RuntimeMessageFormatter : public Misc::MessageFormatParser
|
||||
{
|
||||
std::string formattedMessage;
|
||||
private:
|
||||
std::string mFormattedMessage;
|
||||
Runtime& mRuntime;
|
||||
|
||||
for (std::size_t i=0; i<message.size(); ++i)
|
||||
{
|
||||
char c = message[i];
|
||||
|
||||
if (c!='%')
|
||||
formattedMessage += c;
|
||||
else
|
||||
protected:
|
||||
virtual void visitedPlaceholder(Placeholder placeholder, char padding, int width, int precision)
|
||||
{
|
||||
++i;
|
||||
if (i<message.size())
|
||||
std::ostringstream out;
|
||||
out.fill(padding);
|
||||
if (width != -1)
|
||||
out.width(width);
|
||||
if (precision != -1)
|
||||
out.precision(precision);
|
||||
|
||||
switch (placeholder)
|
||||
{
|
||||
c = message[i];
|
||||
|
||||
if (c=='S' || c=='s')
|
||||
{
|
||||
int index = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
formattedMessage += runtime.getStringLiteral (index);
|
||||
}
|
||||
else if (c=='g' || c=='G')
|
||||
{
|
||||
Type_Integer value = runtime[0].mInteger;
|
||||
runtime.pop();
|
||||
|
||||
std::ostringstream out;
|
||||
out << value;
|
||||
formattedMessage += out.str();
|
||||
}
|
||||
else if (c=='f' || c=='F' || c=='.')
|
||||
{
|
||||
while (c!='f' && i+1<message.size())
|
||||
case StringPlaceholder:
|
||||
{
|
||||
++i;
|
||||
c = message[i];
|
||||
int index = mRuntime[0].mInteger;
|
||||
mRuntime.pop();
|
||||
|
||||
out << mRuntime.getStringLiteral(index);
|
||||
mFormattedMessage += out.str();
|
||||
}
|
||||
break;
|
||||
case IntegerPlaceholder:
|
||||
{
|
||||
Type_Integer value = mRuntime[0].mInteger;
|
||||
mRuntime.pop();
|
||||
|
||||
float value = runtime[0].mFloat;
|
||||
runtime.pop();
|
||||
out << value;
|
||||
mFormattedMessage += out.str();
|
||||
}
|
||||
break;
|
||||
case FloatPlaceholder:
|
||||
{
|
||||
float value = mRuntime[0].mFloat;
|
||||
mRuntime.pop();
|
||||
|
||||
std::ostringstream out;
|
||||
out << value;
|
||||
formattedMessage += out.str();
|
||||
}
|
||||
else if (c=='%')
|
||||
formattedMessage += "%";
|
||||
else
|
||||
{
|
||||
formattedMessage += "%";
|
||||
formattedMessage += c;
|
||||
}
|
||||
out << std::fixed << value;
|
||||
mFormattedMessage += out.str();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void visitedCharacter(char c)
|
||||
{
|
||||
mFormattedMessage += c;
|
||||
}
|
||||
|
||||
public:
|
||||
RuntimeMessageFormatter(Runtime& runtime)
|
||||
: mRuntime(runtime)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void process(const std::string& message)
|
||||
{
|
||||
mFormattedMessage.clear();
|
||||
MessageFormatParser::process(message);
|
||||
}
|
||||
|
||||
std::string getFormattedMessage() const
|
||||
{
|
||||
return mFormattedMessage;
|
||||
}
|
||||
};
|
||||
|
||||
inline std::string formatMessage (const std::string& message, Runtime& runtime)
|
||||
{
|
||||
RuntimeMessageFormatter formatter(runtime);
|
||||
formatter.process(message);
|
||||
|
||||
std::string formattedMessage = formatter.getFormattedMessage();
|
||||
formattedMessage = fixDefinesMsgBox(formattedMessage, runtime.getContext());
|
||||
return formattedMessage;
|
||||
}
|
||||
|
|
68
components/misc/messageformatparser.cpp
Normal file
68
components/misc/messageformatparser.cpp
Normal file
|
@ -0,0 +1,68 @@
|
|||
#include "messageformatparser.hpp"
|
||||
|
||||
namespace Misc
|
||||
{
|
||||
void MessageFormatParser::process(const std::string& m)
|
||||
{
|
||||
for (unsigned int i = 0; i < m.size(); ++i)
|
||||
{
|
||||
if (m[i] == '%')
|
||||
{
|
||||
if (++i < m.size())
|
||||
{
|
||||
if (m[i] == '%')
|
||||
visitedCharacter('%');
|
||||
else
|
||||
{
|
||||
char pad = ' ';
|
||||
if (m[i] == '0' || m[i] == ' ')
|
||||
{
|
||||
pad = m[i];
|
||||
++i;
|
||||
}
|
||||
|
||||
int width = 0;
|
||||
bool widthSet = false;
|
||||
while (i < m.size() && m[i] >= '0' && m[i] <= '9')
|
||||
{
|
||||
width = width * 10 + (m[i] - '0');
|
||||
widthSet = true;
|
||||
++i;
|
||||
}
|
||||
|
||||
if (i < m.size())
|
||||
{
|
||||
int precision = 0;
|
||||
bool precisionSet = false;
|
||||
if (m[i] == '.')
|
||||
{
|
||||
while (++i < m.size() && m[i] >= '0' && m[i] <= '9')
|
||||
{
|
||||
precision = precision * 10 + (m[i] - '0');
|
||||
precisionSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (i < m.size())
|
||||
{
|
||||
width = (widthSet) ? width : -1;
|
||||
precision = (precisionSet) ? precision : -1;
|
||||
|
||||
if (m[i] == 'S' || m[i] == 's')
|
||||
visitedPlaceholder(StringPlaceholder, pad, width, precision);
|
||||
else if (m[i] == 'g' || m[i] == 'G')
|
||||
visitedPlaceholder(IntegerPlaceholder, pad, width, precision);
|
||||
else if (m[i] == 'f' || m[i] == 'F')
|
||||
visitedPlaceholder(FloatPlaceholder, pad, width, precision);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
visitedCharacter(m[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
26
components/misc/messageformatparser.hpp
Normal file
26
components/misc/messageformatparser.hpp
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef OPENMW_COMPONENTS_MISC_MESSAGEFORMATPARSER_H
|
||||
#define OPENMW_COMPONENTS_MISC_MESSAGEFORMATPARSER_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Misc
|
||||
{
|
||||
class MessageFormatParser
|
||||
{
|
||||
protected:
|
||||
enum Placeholder
|
||||
{
|
||||
StringPlaceholder,
|
||||
IntegerPlaceholder,
|
||||
FloatPlaceholder
|
||||
};
|
||||
|
||||
virtual void visitedPlaceholder(Placeholder placeholder, char padding, int width, int precision) = 0;
|
||||
virtual void visitedCharacter(char c) = 0;
|
||||
|
||||
public:
|
||||
virtual void process(const std::string& message);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue