MsgHandler.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // Copyright 2008 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "Common/MsgHandler.h"
  4. #include <cstdarg>
  5. #include <cstdlib>
  6. #include <string>
  7. #ifdef _WIN32
  8. #include <windows.h>
  9. #else
  10. #include <cstdio>
  11. #include <fmt/format.h>
  12. #endif
  13. #include "Common/Common.h"
  14. #include "Common/CommonTypes.h"
  15. #include "Common/Logging/Log.h"
  16. #include "Common/StringUtil.h"
  17. namespace Common
  18. {
  19. namespace
  20. {
  21. // Default non library dependent panic alert
  22. bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, MsgType style)
  23. {
  24. #ifdef _WIN32
  25. int window_style = MB_ICONINFORMATION;
  26. if (style == MsgType::Question)
  27. window_style = MB_ICONQUESTION;
  28. if (style == MsgType::Warning)
  29. window_style = MB_ICONWARNING;
  30. return IDYES == MessageBox(0, UTF8ToTStr(text).c_str(), UTF8ToTStr(caption).c_str(),
  31. window_style | (yes_no ? MB_YESNO : MB_OK));
  32. #else
  33. fmt::print(stderr, "{}\n", text);
  34. // Return no to any question (which will in general crash the emulator)
  35. return false;
  36. #endif
  37. }
  38. // Default (non) translator
  39. std::string DefaultStringTranslator(const char* text)
  40. {
  41. return text;
  42. }
  43. MsgAlertHandler s_msg_handler = DefaultMsgHandler;
  44. StringTranslator s_str_translator = DefaultStringTranslator;
  45. bool s_alert_enabled = true;
  46. bool s_abort_on_panic_alert = false;
  47. const char* GetCaption(MsgType style)
  48. {
  49. static const std::string info_caption = GetStringT("Information");
  50. static const std::string ques_caption = GetStringT("Question");
  51. static const std::string warn_caption = GetStringT("Warning");
  52. static const std::string crit_caption = GetStringT("Critical");
  53. switch (style)
  54. {
  55. case MsgType::Information:
  56. return info_caption.c_str();
  57. case MsgType::Question:
  58. return ques_caption.c_str();
  59. case MsgType::Warning:
  60. return warn_caption.c_str();
  61. case MsgType::Critical:
  62. return crit_caption.c_str();
  63. default:
  64. return "Unhandled caption";
  65. }
  66. }
  67. } // Anonymous namespace
  68. // Select which of these functions that are used for message boxes. If
  69. // Qt is enabled we will use QtMsgAlertHandler() that is defined in Main.cpp
  70. void RegisterMsgAlertHandler(MsgAlertHandler handler)
  71. {
  72. s_msg_handler = handler;
  73. }
  74. // Select translation function.
  75. void RegisterStringTranslator(StringTranslator translator)
  76. {
  77. s_str_translator = translator;
  78. }
  79. // enable/disable the alert handler
  80. void SetEnableAlert(bool enable)
  81. {
  82. s_alert_enabled = enable;
  83. }
  84. void SetAbortOnPanicAlert(bool should_abort)
  85. {
  86. s_abort_on_panic_alert = should_abort;
  87. }
  88. std::string GetStringT(const char* string)
  89. {
  90. return s_str_translator(string);
  91. }
  92. static bool ShowMessageAlert(std::string_view text, bool yes_no, Common::Log::LogType log_type,
  93. MsgType style, const char* file, int line)
  94. {
  95. const char* caption = GetCaption(style);
  96. // Directly call GenericLogFmt rather than using the normal log macros so that we can use the
  97. // caller's line file and line number
  98. Common::Log::GenericLogFmt<2>(Common::Log::LogLevel::LERROR, log_type, file, line,
  99. FMT_STRING("{}: {}"), caption, text);
  100. // Panic alerts.
  101. if (style == MsgType::Warning && s_abort_on_panic_alert)
  102. {
  103. std::abort();
  104. }
  105. // Don't ignore questions, especially AskYesNo, PanicYesNo could be ignored
  106. if (s_msg_handler != nullptr &&
  107. (s_alert_enabled || style == MsgType::Question || style == MsgType::Critical))
  108. {
  109. return s_msg_handler(caption, text.data(), yes_no, style);
  110. }
  111. return true;
  112. }
  113. // This is the first stop for gui alerts where the log is updated and the
  114. // correct window is shown, when using fmt
  115. bool MsgAlertFmtImpl(bool yes_no, MsgType style, Common::Log::LogType log_type, const char* file,
  116. int line, fmt::string_view format, const fmt::format_args& args)
  117. {
  118. const auto message = fmt::vformat(format, args);
  119. return ShowMessageAlert(message, yes_no, log_type, style, file, line);
  120. }
  121. } // namespace Common