From 3f5698b1e0d49260cb04ba76d693eee70df86ca7 Mon Sep 17 00:00:00 2001 From: Ted John Date: Sat, 13 Feb 2021 00:15:27 +0000 Subject: [PATCH] Fix REPL write line on Linux --- src/openrct2-ui/windows/ObjectLoadError.cpp | 14 ++++++----- src/openrct2/Context.cpp | 5 ++++ src/openrct2/Context.h | 1 + src/openrct2/Diagnostic.cpp | 16 +++++++++---- src/openrct2/Game.cpp | 2 +- src/openrct2/core/Console.cpp | 22 ++++++++++++++---- src/openrct2/core/Http.WinHttp.cpp | 3 ++- src/openrct2/interface/InteractiveConsole.h | 1 + src/openrct2/interface/Screenshot.cpp | 2 +- src/openrct2/interface/StdInOutConsole.cpp | 23 +++++++++++++++---- src/openrct2/network/NetworkBase.cpp | 2 +- .../network/NetworkServerAdvertiser.cpp | 3 ++- src/openrct2/scripting/Duktape.hpp | 3 ++- src/openrct2/scripting/ScriptEngine.cpp | 6 ++--- src/thirdparty/linenoise.hpp | 9 +++++++- 15 files changed, 82 insertions(+), 30 deletions(-) diff --git a/src/openrct2-ui/windows/ObjectLoadError.cpp b/src/openrct2-ui/windows/ObjectLoadError.cpp index f9ff3bdbca..644c56d516 100644 --- a/src/openrct2-ui/windows/ObjectLoadError.cpp +++ b/src/openrct2-ui/windows/ObjectLoadError.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -153,7 +154,7 @@ private: { try { - std::printf("Downloading %s\n", url.c_str()); + Console::WriteLine("Downloading %s", url.c_str()); Http::Request req; req.method = Http::Method::GET; req.url = url; @@ -175,14 +176,14 @@ private: } else { - std::printf(" Failed to download %s\n", name.c_str()); + Console::Error::WriteLine(" Failed to download %s", name.c_str()); } QueueNextDownload(); }); } catch (const std::exception&) { - std::printf(" Failed to download %s\n", name.c_str()); + Console::Error::WriteLine(" Failed to download %s", name.c_str()); QueueNextDownload(); } } @@ -226,19 +227,20 @@ private: } else if (response.status == Http::Status::NotFound) { - std::printf(" %s not found\n", name.c_str()); + Console::Error::WriteLine(" %s not found", name.c_str()); QueueNextDownload(); } else { - std::printf(" %s query failed (status %d)\n", name.c_str(), static_cast(response.status)); + Console::Error::WriteLine( + " %s query failed (status %d)", name.c_str(), static_cast(response.status)); QueueNextDownload(); } }); } catch (const std::exception&) { - std::printf(" Failed to query %s\n", name.c_str()); + Console::Error::WriteLine(" Failed to query %s", name.c_str()); } } }; diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index 208311b36f..3f1f685e76 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -273,6 +273,11 @@ namespace OpenRCT2 _stdInOutConsole.WriteLine(s); } + void WriteErrorLine(const std::string& s) override + { + _stdInOutConsole.WriteLineError(s); + } + /** * Causes the OpenRCT2 game loop to finish. */ diff --git a/src/openrct2/Context.h b/src/openrct2/Context.h index ed88b99bf0..967ac662b7 100644 --- a/src/openrct2/Context.h +++ b/src/openrct2/Context.h @@ -141,6 +141,7 @@ namespace OpenRCT2 virtual bool LoadParkFromStream( IStream* stream, const std::string& path, bool loadTitleScreenFirstOnFail = false) abstract; virtual void WriteLine(const std::string& s) abstract; + virtual void WriteErrorLine(const std::string& s) abstract; virtual void Finish() abstract; virtual void Quit() abstract; diff --git a/src/openrct2/Diagnostic.cpp b/src/openrct2/Diagnostic.cpp index 5e67b05261..90cf9f9d71 100644 --- a/src/openrct2/Diagnostic.cpp +++ b/src/openrct2/Diagnostic.cpp @@ -9,6 +9,7 @@ #include "Diagnostic.h" +#include "core/Console.hpp" #include "core/String.hpp" #include @@ -73,6 +74,15 @@ static constexpr const char* _level_strings[] = { "FATAL", "ERROR", "WARNING", "VERBOSE", "INFO", }; +static void diagnostic_print(DiagnosticLevel level, const std::string& prefix, const std::string& msg) +{ + auto stream = diagnostic_get_stream(level); + if (stream == stdout) + Console::WriteLine("%s%s", prefix.c_str(), msg.c_str()); + else + Console::Error::WriteLine("%s%s", prefix.c_str(), msg.c_str()); +} + void diagnostic_log(DiagnosticLevel diagnosticLevel, const char* format, ...) { va_list args; @@ -86,8 +96,7 @@ void diagnostic_log(DiagnosticLevel diagnosticLevel, const char* format, ...) auto msg = String::StdFormat_VA(format, args); va_end(args); - auto stream = diagnostic_get_stream(diagnosticLevel); - fprintf(stream, "%s%s\n", prefix.c_str(), msg.c_str()); + diagnostic_print(diagnosticLevel, prefix, msg); } } @@ -114,8 +123,7 @@ void diagnostic_log_with_location( auto msg = String::StdFormat_VA(format, args); va_end(args); - auto stream = diagnostic_get_stream(diagnosticLevel); - fprintf(stream, "%s%s\n", prefix.c_str(), msg.c_str()); + diagnostic_print(diagnosticLevel, prefix, msg); } } diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index f1e15ab889..0cc621ccf2 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -762,7 +762,7 @@ void game_autosave() } if (!scenario_save(path, saveFlags)) - std::fprintf(stderr, "Could not autosave the scenario. Is the save folder writeable?\n"); + Console::Error::WriteLine("Could not autosave the scenario. Is the save folder writeable?"); } static void game_load_or_quit_no_save_prompt_callback(int32_t result, const utf8* path) diff --git a/src/openrct2/core/Console.cpp b/src/openrct2/core/Console.cpp index 4eb371b4d5..a5170934b7 100644 --- a/src/openrct2/core/Console.cpp +++ b/src/openrct2/core/Console.cpp @@ -9,6 +9,7 @@ #include "Console.hpp" +#include "../Context.h" #include "../platform/platform.h" #include @@ -49,10 +50,16 @@ namespace Console void WriteLine(const utf8* format, ...) { va_list args; - va_start(args, format); - auto formatLn = std::string(format) + "\n"; - vfprintf(stdout, formatLn.c_str(), args); + + char buffer[4096]; + std::vsnprintf(buffer, sizeof(buffer), format, args); + auto ctx = OpenRCT2::GetContext(); + if (ctx != nullptr) + ctx->WriteLine(buffer); + else + std::printf("%s\n", buffer); + va_end(args); } @@ -92,8 +99,13 @@ namespace Console void WriteLine_VA(const utf8* format, va_list args) { - auto formatLn = std::string(format) + "\n"; - vfprintf(stdout, formatLn.c_str(), args); + char buffer[4096]; + std::vsnprintf(buffer, sizeof(buffer), format, args); + auto ctx = OpenRCT2::GetContext(); + if (ctx != nullptr) + ctx->WriteErrorLine(buffer); + else + std::printf("%s\n", buffer); } } // namespace Error } // namespace Console diff --git a/src/openrct2/core/Http.WinHttp.cpp b/src/openrct2/core/Http.WinHttp.cpp index d51e0cc930..b76df5f420 100644 --- a/src/openrct2/core/Http.WinHttp.cpp +++ b/src/openrct2/core/Http.WinHttp.cpp @@ -12,6 +12,7 @@ # include "Http.h" # include "../Version.h" +# include "../core/Console.hpp" # include "String.hpp" # include @@ -226,7 +227,7 @@ namespace Http catch ([[maybe_unused]] const std::exception& e) { # ifdef DEBUG - std::fprintf(stderr, "HTTP request failed: %s\n", e.what()); + Console::Error::WriteLine("HTTP request failed: %s", e.what()); # endif WinHttpCloseHandle(hSession); WinHttpCloseHandle(hConnect); diff --git a/src/openrct2/interface/InteractiveConsole.h b/src/openrct2/interface/InteractiveConsole.h index 0f24115de6..a549703f2a 100644 --- a/src/openrct2/interface/InteractiveConsole.h +++ b/src/openrct2/interface/InteractiveConsole.h @@ -53,6 +53,7 @@ class StdInOutConsole final : public InteractiveConsole { private: std::queue, std::string>> _evalQueue; + bool _isPromptShowing{}; public: void Start(); diff --git a/src/openrct2/interface/Screenshot.cpp b/src/openrct2/interface/Screenshot.cpp index 9e1a8d5c8a..a50981552d 100644 --- a/src/openrct2/interface/Screenshot.cpp +++ b/src/openrct2/interface/Screenshot.cpp @@ -510,7 +510,7 @@ static void benchgfx_render_screenshots(const char* inputPath, std::unique_ptr @@ -195,7 +196,7 @@ namespace OpenRCT2::Scripting { duk_set_top(_ctx, _top); _ctx = {}; - std::fprintf(stderr, "duktape stack was not returned to original state!"); + Console::Error::WriteLine("duktape stack was not returned to original state!"); } _ctx = {}; } diff --git a/src/openrct2/scripting/ScriptEngine.cpp b/src/openrct2/scripting/ScriptEngine.cpp index 2ebc1305df..879f4f1ed5 100644 --- a/src/openrct2/scripting/ScriptEngine.cpp +++ b/src/openrct2/scripting/ScriptEngine.cpp @@ -528,7 +528,7 @@ void ScriptEngine::SetupHotReloading() } catch (const std::exception& e) { - std::fprintf(stderr, "Unable to enable hot reloading of plugins: %s\n", e.what()); + Console::Error::WriteLine("Unable to enable hot reloading of plugins: %s", e.what()); } } @@ -1199,7 +1199,7 @@ void ScriptEngine::LoadSharedStorage() } catch (const std::exception&) { - fprintf(stderr, "Unable to read '%s'\n", path.c_str()); + Console::Error::WriteLine("Unable to read '%s'", path.c_str()); } } @@ -1216,7 +1216,7 @@ void ScriptEngine::SaveSharedStorage() } catch (const std::exception&) { - fprintf(stderr, "Unable to write to '%s'\n", path.c_str()); + Console::Error::WriteLine("Unable to write to '%s'", path.c_str()); } } diff --git a/src/thirdparty/linenoise.hpp b/src/thirdparty/linenoise.hpp index fb7d28aaae..70199dc4a9 100644 --- a/src/thirdparty/linenoise.hpp +++ b/src/thirdparty/linenoise.hpp @@ -1094,6 +1094,8 @@ struct linenoiseState { int history_index; /* The history index we are currently editing. */ }; +static struct linenoiseState lnstate; + enum KEY_ACTION { KEY_NULL = 0, /* NULL */ CTRL_A = 1, /* Ctrl+a */ @@ -2088,6 +2090,11 @@ inline void linenoiseEditDeletePrevWord(struct linenoiseState *l) { refreshLine(l); } +inline void linenoiseEditRefreshLine() +{ + refreshLine(&lnstate); +} + /* This function is the core of the line editing capability of linenoise. * It expects 'fd' to be already in "raw mode" so that every key pressed * will be returned ASAP to read(). @@ -2098,7 +2105,7 @@ inline void linenoiseEditDeletePrevWord(struct linenoiseState *l) { * The function returns the length of the current buffer. */ inline int linenoiseEdit(int stdin_fd, int stdout_fd, char *buf, int buflen, const char *prompt) { - struct linenoiseState l; + auto& l = lnstate; /* Populate the linenoise state that we pass to functions implementing * specific editing functionalities. */