mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-30 17:56:39 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			165 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			165 lines
		
	
	
	
		
			4.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #ifndef INTERPRETER_MISCOPCODES_H_INCLUDED
 | |
| #define INTERPRETER_MISCOPCODES_H_INCLUDED
 | |
| 
 | |
| #include <algorithm>
 | |
| #include <sstream>
 | |
| #include <stdexcept>
 | |
| #include <string>
 | |
| #include <vector>
 | |
| 
 | |
| #include "defines.hpp"
 | |
| #include "opcodes.hpp"
 | |
| #include "runtime.hpp"
 | |
| 
 | |
| #include <components/misc/messageformatparser.hpp>
 | |
| 
 | |
| namespace Interpreter
 | |
| {
 | |
|     class RuntimeMessageFormatter : public Misc::MessageFormatParser
 | |
|     {
 | |
|     private:
 | |
|         std::string mFormattedMessage;
 | |
|         Runtime& mRuntime;
 | |
| 
 | |
|     protected:
 | |
|         void visitedPlaceholder(
 | |
|             Placeholder placeholder, char padding, int width, int precision, Notation notation) override
 | |
|         {
 | |
|             std::ostringstream out;
 | |
|             out.fill(padding);
 | |
|             if (width != -1)
 | |
|                 out.width(width);
 | |
|             if (precision != -1)
 | |
|                 out.precision(precision);
 | |
| 
 | |
|             switch (placeholder)
 | |
|             {
 | |
|                 case StringPlaceholder:
 | |
|                 {
 | |
|                     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();
 | |
| 
 | |
|                     if (notation == FixedNotation)
 | |
|                     {
 | |
|                         out << std::fixed << value;
 | |
|                         mFormattedMessage += out.str();
 | |
|                     }
 | |
|                     else if (notation == ShortestNotation)
 | |
|                     {
 | |
|                         out << value;
 | |
|                         std::string standard = out.str();
 | |
| 
 | |
|                         out.str(std::string());
 | |
|                         out.clear();
 | |
| 
 | |
|                         out << std::scientific << value;
 | |
|                         std::string scientific = out.str();
 | |
| 
 | |
|                         mFormattedMessage += standard.length() < scientific.length() ? standard : scientific;
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         out << std::scientific << value;
 | |
|                         mFormattedMessage += out.str();
 | |
|                     }
 | |
|                 }
 | |
|                 break;
 | |
|                 default:
 | |
|                     break;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void visitedCharacter(char c) override { mFormattedMessage += c; }
 | |
| 
 | |
|     public:
 | |
|         RuntimeMessageFormatter(Runtime& runtime)
 | |
|             : mRuntime(runtime)
 | |
|         {
 | |
|         }
 | |
| 
 | |
|         void process(std::string_view message) override
 | |
|         {
 | |
|             mFormattedMessage.clear();
 | |
|             MessageFormatParser::process(message);
 | |
|         }
 | |
| 
 | |
|         std::string getFormattedMessage() const { return mFormattedMessage; }
 | |
|     };
 | |
| 
 | |
|     inline std::string formatMessage(std::string_view message, Runtime& runtime)
 | |
|     {
 | |
|         RuntimeMessageFormatter formatter(runtime);
 | |
|         formatter.process(message);
 | |
| 
 | |
|         std::string formattedMessage = formatter.getFormattedMessage();
 | |
|         formattedMessage = fixDefinesMsgBox(formattedMessage, runtime.getContext());
 | |
|         return formattedMessage;
 | |
|     }
 | |
| 
 | |
|     class OpMessageBox : public Opcode1
 | |
|     {
 | |
|     public:
 | |
|         void execute(Runtime& runtime, unsigned int arg0) override
 | |
|         {
 | |
|             // message
 | |
|             int index = runtime[0].mInteger;
 | |
|             runtime.pop();
 | |
|             std::string_view message = runtime.getStringLiteral(index);
 | |
| 
 | |
|             // buttons
 | |
|             std::vector<std::string> buttons;
 | |
| 
 | |
|             for (std::size_t i = 0; i < arg0; ++i)
 | |
|             {
 | |
|                 index = runtime[0].mInteger;
 | |
|                 runtime.pop();
 | |
|                 buttons.emplace_back(runtime.getStringLiteral(index));
 | |
|             }
 | |
| 
 | |
|             std::reverse(buttons.begin(), buttons.end());
 | |
| 
 | |
|             // handle additional parameters
 | |
|             std::string formattedMessage = formatMessage(message, runtime);
 | |
| 
 | |
|             runtime.getContext().messageBox(formattedMessage, buttons);
 | |
|         }
 | |
|     };
 | |
| 
 | |
|     class OpReport : public Opcode0
 | |
|     {
 | |
|     public:
 | |
|         void execute(Runtime& runtime) override
 | |
|         {
 | |
|             // message
 | |
|             int index = runtime[0].mInteger;
 | |
|             runtime.pop();
 | |
|             std::string_view message = runtime.getStringLiteral(index);
 | |
| 
 | |
|             // handle additional parameters
 | |
|             std::string formattedMessage = formatMessage(message, runtime);
 | |
| 
 | |
|             runtime.getContext().report(formattedMessage);
 | |
|         }
 | |
|     };
 | |
| 
 | |
| }
 | |
| 
 | |
| #endif
 |