1 // Copyright 2008 Dolphin Emulator Project
2 // Licensed under GPLv2+
3 // Refer to the license.txt file included.
4 
5 #include "Common/MsgHandler.h"
6 
7 #include <cstdarg>
8 #include <string>
9 
10 #ifdef _WIN32
11 #include <windows.h>
12 #else
13 #include <cstdio>
14 #include <fmt/format.h>
15 #endif
16 
17 #include "Common/Common.h"
18 #include "Common/CommonTypes.h"
19 #include "Common/Logging/Log.h"
20 #include "Common/StringUtil.h"
21 
22 namespace Common
23 {
24 namespace
25 {
26 // Default non library dependent panic alert
DefaultMsgHandler(const char * caption,const char * text,bool yes_no,MsgType style)27 bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, MsgType style)
28 {
29 #ifdef _WIN32
30   int window_style = MB_ICONINFORMATION;
31   if (style == MsgType::Question)
32     window_style = MB_ICONQUESTION;
33   if (style == MsgType::Warning)
34     window_style = MB_ICONWARNING;
35 
36   return IDYES == MessageBox(0, UTF8ToTStr(text).c_str(), UTF8ToTStr(caption).c_str(),
37                              window_style | (yes_no ? MB_YESNO : MB_OK));
38 #else
39   fmt::print(stderr, "{}\n", text);
40 
41   // Return no to any question (which will in general crash the emulator)
42   return false;
43 #endif
44 }
45 
46 // Default (non) translator
DefaultStringTranslator(const char * text)47 std::string DefaultStringTranslator(const char* text)
48 {
49   return text;
50 }
51 
52 MsgAlertHandler s_msg_handler = DefaultMsgHandler;
53 StringTranslator s_str_translator = DefaultStringTranslator;
54 bool s_alert_enabled = true;
55 }  // Anonymous namespace
56 
57 // Select which of these functions that are used for message boxes. If
58 // Qt is enabled we will use QtMsgAlertHandler() that is defined in Main.cpp
RegisterMsgAlertHandler(MsgAlertHandler handler)59 void RegisterMsgAlertHandler(MsgAlertHandler handler)
60 {
61   s_msg_handler = handler;
62 }
63 
64 // Select translation function.
RegisterStringTranslator(StringTranslator translator)65 void RegisterStringTranslator(StringTranslator translator)
66 {
67   s_str_translator = translator;
68 }
69 
70 // enable/disable the alert handler
SetEnableAlert(bool enable)71 void SetEnableAlert(bool enable)
72 {
73   s_alert_enabled = enable;
74 }
75 
GetStringT(const char * string)76 std::string GetStringT(const char* string)
77 {
78   return s_str_translator(string);
79 }
80 
81 // This is the first stop for gui alerts where the log is updated and the
82 // correct window is shown
MsgAlert(bool yes_no,MsgType style,const char * format,...)83 bool MsgAlert(bool yes_no, MsgType style, const char* format, ...)
84 {
85   // Read message and write it to the log
86   const char* caption = "";
87   char buffer[2048];
88 
89   static const std::string info_caption = s_str_translator(_trans("Information"));
90   static const std::string warn_caption = s_str_translator(_trans("Question"));
91   static const std::string ques_caption = s_str_translator(_trans("Warning"));
92   static const std::string crit_caption = s_str_translator(_trans("Critical"));
93 
94   switch (style)
95   {
96   case MsgType::Information:
97     caption = info_caption.c_str();
98     break;
99   case MsgType::Question:
100     caption = ques_caption.c_str();
101     break;
102   case MsgType::Warning:
103     caption = warn_caption.c_str();
104     break;
105   case MsgType::Critical:
106     caption = crit_caption.c_str();
107     break;
108   }
109 
110   va_list args;
111   va_start(args, format);
112   CharArrayFromFormatV(buffer, sizeof(buffer) - 1, s_str_translator(format).c_str(), args);
113   va_end(args);
114 
115   ERROR_LOG(MASTER_LOG, "%s: %s", caption, buffer);
116 
117   // Don't ignore questions, especially AskYesNo, PanicYesNo could be ignored
118   if (s_msg_handler != nullptr &&
119       (s_alert_enabled || style == MsgType::Question || style == MsgType::Critical))
120   {
121     return s_msg_handler(caption, buffer, yes_no, style);
122   }
123 
124   return true;
125 }
126 }  // namespace Common
127