mirror of
https://github.com/OpenMW/openmw.git
synced 2025-03-03 15:09:39 +00:00
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
|
add_component_dir (misc
|
||||||
utf8stream stringops resourcehelpers rng
|
utf8stream stringops resourcehelpers rng messageformatparser
|
||||||
)
|
)
|
||||||
|
|
||||||
IF(NOT WIN32 AND NOT APPLE)
|
IF(NOT WIN32 AND NOT APPLE)
|
||||||
|
|
|
@ -140,30 +140,9 @@ namespace Compiler
|
||||||
|
|
||||||
if (mState==MessageState || mState==MessageCommaState)
|
if (mState==MessageState || mState==MessageCommaState)
|
||||||
{
|
{
|
||||||
std::string arguments;
|
GetArgumentsFromMessageFormat processor;
|
||||||
|
processor.process(name);
|
||||||
for (std::size_t i=0; i<name.size(); ++i)
|
std::string arguments = processor.getArguments();
|
||||||
{
|
|
||||||
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';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!arguments.empty())
|
if (!arguments.empty())
|
||||||
{
|
{
|
||||||
|
@ -577,4 +556,23 @@ namespace Compiler
|
||||||
mName.clear();
|
mName.clear();
|
||||||
mExplicit.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
|
#define COMPILER_LINEPARSER_H_INCLUDED
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <components/interpreter/types.hpp>
|
#include <components/interpreter/types.hpp>
|
||||||
|
#include <components/misc/messageformatparser.hpp>
|
||||||
|
|
||||||
#include "parser.hpp"
|
#include "parser.hpp"
|
||||||
#include "exprparser.hpp"
|
#include "exprparser.hpp"
|
||||||
|
@ -74,6 +76,24 @@ namespace Compiler
|
||||||
void reset();
|
void reset();
|
||||||
///< Reset parser to clean state.
|
///< 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
|
#endif
|
||||||
|
|
|
@ -13,67 +13,89 @@
|
||||||
#include "defines.hpp"
|
#include "defines.hpp"
|
||||||
|
|
||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
|
#include <components/misc/messageformatparser.hpp>
|
||||||
|
|
||||||
namespace Interpreter
|
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)
|
protected:
|
||||||
{
|
virtual void visitedPlaceholder(Placeholder placeholder, char padding, int width, int precision)
|
||||||
char c = message[i];
|
|
||||||
|
|
||||||
if (c!='%')
|
|
||||||
formattedMessage += c;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
++i;
|
std::ostringstream out;
|
||||||
if (i<message.size())
|
out.fill(padding);
|
||||||
|
if (width != -1)
|
||||||
|
out.width(width);
|
||||||
|
if (precision != -1)
|
||||||
|
out.precision(precision);
|
||||||
|
|
||||||
|
switch (placeholder)
|
||||||
{
|
{
|
||||||
c = message[i];
|
case StringPlaceholder:
|
||||||
|
|
||||||
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())
|
|
||||||
{
|
{
|
||||||
++i;
|
int index = mRuntime[0].mInteger;
|
||||||
c = message[i];
|
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;
|
out << value;
|
||||||
runtime.pop();
|
mFormattedMessage += out.str();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FloatPlaceholder:
|
||||||
|
{
|
||||||
|
float value = mRuntime[0].mFloat;
|
||||||
|
mRuntime.pop();
|
||||||
|
|
||||||
std::ostringstream out;
|
out << std::fixed << value;
|
||||||
out << value;
|
mFormattedMessage += out.str();
|
||||||
formattedMessage += out.str();
|
}
|
||||||
}
|
break;
|
||||||
else if (c=='%')
|
default:
|
||||||
formattedMessage += "%";
|
break;
|
||||||
else
|
|
||||||
{
|
|
||||||
formattedMessage += "%";
|
|
||||||
formattedMessage += c;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
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());
|
formattedMessage = fixDefinesMsgBox(formattedMessage, runtime.getContext());
|
||||||
return formattedMessage;
|
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