Merge pull request #992 from MiroslavR/msgformat

Improve format specifiers for message boxes
pull/1/head
scrawl 9 years ago committed by GitHub
commit c842d4976e

@ -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;
for (std::size_t i=0; i<message.size(); ++i)
{
char c = message[i];
private:
std::string mFormattedMessage;
Runtime& mRuntime;
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();
out << value;
mFormattedMessage += out.str();
}
break;
case FloatPlaceholder:
{
float value = mRuntime[0].mFloat;
mRuntime.pop();
float value = runtime[0].mFloat;
runtime.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;
}

@ -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]);
}
}
}
}

@ -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…
Cancel
Save