From 9fc65e646c6f4e8354ecabfd4ae25f0a2ffa9367 Mon Sep 17 00:00:00 2001 From: Celtic Minstrel Date: Sun, 28 Feb 2021 02:55:47 -0500 Subject: [PATCH] Add command-line options to disable the Windows-specific special log/console handling --- src/commandline_options.cpp | 46 ++++++++++++++++++------------------- src/log_windows.cpp | 12 ++++++++-- src/log_windows.hpp | 2 +- src/wesnoth.cpp | 22 ++++++++++++++---- 4 files changed, 51 insertions(+), 31 deletions(-) diff --git a/src/commandline_options.cpp b/src/commandline_options.cpp index 44f74537089bf..f9faff71f8cfe 100644 --- a/src/commandline_options.cpp +++ b/src/commandline_options.cpp @@ -60,6 +60,14 @@ bad_commandline_tuple::bad_commandline_tuple(const std::string& str, { } + +#ifdef _WIN32 +#define IMPLY_WCONSOLE " Implies --wconsole." +#else +#define IMPLY_WCONSOLE +#endif // _WIN32 + + commandline_options::commandline_options(const std::vector& args) : bunzip2() , bzip2() @@ -173,7 +181,7 @@ commandline_options::commandline_options(const std::vector& args) ("config-path", "prints the path of the userdata directory and exits. DEPRECATED: use userdata-path instead.") ("core", po::value(), "overrides the loaded core with the one whose id is specified.") ("data-dir", po::value(), "overrides the data directory with the one specified.") - ("data-path", "prints the path of the data directory and exits.") + ("data-path", "prints the path of the data directory and exits." IMPLY_WCONSOLE) ("debug,d", "enables additional command mode options in-game.") ("debug-lua", "enables some Lua debugging mechanisms") ("strict-lua", "disallow deprecated Lua API calls") @@ -184,7 +192,7 @@ commandline_options::commandline_options(const std::vector& args) ("editor,e", po::value()->implicit_value(std::string()), "starts the in-game map editor directly. If file is specified, equivalent to -e --load .") ("gunzip", po::value(), "decompresses a file (.gz) in gzip format and stores it without the .gz suffix. .gz will be removed.") ("gzip", po::value(), "compresses a file () in gzip format, stores it as .gz and removes .") - ("help,h", "prints this message and exits.") + ("help,h", "prints this message and exits." IMPLY_WCONSOLE) ("language,L", po::value(), "uses language (symbol) this session. Example: --language ang_GB@latin") ("load,l", po::value(), "loads the save from the standard save game directory. When launching the map editor via -e, the map is loaded, relative to the current directory. If it is a directory, the editor will start with a load map dialog opened there.") ("noaddons", "disables the loading of all add-ons.") @@ -194,22 +202,10 @@ commandline_options::commandline_options(const std::vector& args) ("nosound", "runs the game without sounds and music.") ("password", po::value(), "uses when connecting to a server, ignoring other preferences.") ("plugin", po::value(), "(experimental) load a script which defines a wesnoth plugin. similar to --script below, but Lua file should return a function which will be run as a coroutine and periodically woken up with updates.") - ("render-image", po::value()->multitoken(), "takes two arguments: . Like screenshot, but instead of a map, takes a valid Wesnoth 'image path string' with image path functions, and writes it to a .png file." -#ifdef _WIN32 - " Implies --wconsole." -#endif // _WIN32 - ) - ("report,R", "initializes game directories, prints build information suitable for use in bug reports, and exits." -#ifdef _WIN32 - " Implies --wconsole." -#endif // _WIN32 - ) + ("render-image", po::value()->multitoken(), "takes two arguments: . Like screenshot, but instead of a map, takes a valid Wesnoth 'image path string' with image path functions, and writes it to a .png file." IMPLY_WCONSOLE) + ("report,R", "initializes game directories, prints build information suitable for use in bug reports, and exits." IMPLY_WCONSOLE) ("rng-seed", po::value(), "seeds the random number generator with number . Example: --rng-seed 0") - ("screenshot", po::value()->multitoken(), "takes two arguments: . Saves a screenshot of to without initializing a screen. Editor must be compiled in for this to work." -#ifdef _WIN32 - " Implies --wconsole." -#endif // _WIN32 - ) + ("screenshot", po::value()->multitoken(), "takes two arguments: . Saves a screenshot of to without initializing a screen. Editor must be compiled in for this to work." IMPLY_WCONSOLE) ("script", po::value(), "(experimental) file containing a Lua script to control the client") ("server,s", po::value()->implicit_value(std::string()), "connects to the host if specified or to the first host in your preferences.") ("strict-validation", "makes validation errors fatal") @@ -218,13 +214,15 @@ commandline_options::commandline_options(const std::vector& args) ("userconfig-dir", po::value(), "sets the path of the user config directory to $HOME/ or My Documents\\My Games\\ for Windows. You can specify also an absolute path outside the $HOME or My Documents\\My Games directory. Defaults to $HOME/.config/wesnoth on X11 and to the userdata-dir on other systems.") ("userconfig-path", "prints the path of the user config directory and exits.") ("userdata-dir", po::value(), "sets the path of the userdata directory to $HOME/ or My Documents\\My Games\\ for Windows. You can specify also an absolute path outside the $HOME or My Documents\\My Games directory.") - ("userdata-path", "prints the path of the userdata directory and exits.") + ("userdata-path", "prints the path of the userdata directory and exits." IMPLY_WCONSOLE) ("username", po::value(), "uses when connecting to a server, ignoring other preferences.") ("validcache", "assumes that the cache is valid. (dangerous)") ("version,v", "prints the game's version number and exits.") ("with-replay", "replays the file loaded with the --load option.") #ifdef _WIN32 ("wconsole", "attaches a console window on startup (Windows only). Implied by any option that prints something and exits.") + ("wnoconsole", "don't attach a console window on startup (Windows only). Overrides options that imply --wconsole.") + ("wnoredirect", "disables standard redirection of logging to a file (Windows only), allowing the output to be piped to another command") #endif // _WIN32 ; @@ -248,7 +246,7 @@ commandline_options::commandline_options(const std::vector& args) po::options_description logging_opts("Logging options"); logging_opts.add_options() - ("logdomains", po::value()->implicit_value(std::string()), "lists defined log domains (only the ones containing filter if such is provided) and exits.") + ("logdomains", po::value()->implicit_value(std::string()), "lists defined log domains (only the ones containing filter if such is provided) and exits." IMPLY_WCONSOLE) ("log-error", po::value(), "sets the severity level of the specified log domain(s) to 'error'. should be given as a comma-separated list of domains, wildcards are allowed. Example: --log-error=network,gui/*,engine/enemies") ("log-warning", po::value(), "sets the severity level of the specified log domain(s) to 'warning'. Similar to --log-error.") ("log-info", po::value(), "sets the severity level of the specified log domain(s) to 'info'. Similar to --log-error.") @@ -289,14 +287,14 @@ commandline_options::commandline_options(const std::vector& args) po::options_description parsing_opts("WML parsing options"); parsing_opts.add_options() ("use-schema,S", po::value(), "specify a schema to validate WML against (defaults to the core schema)") - ("validate,V", po::value(), "validate a specified WML file against a schema") + ("validate,V", po::value(), "validate a specified WML file against a schema" IMPLY_WCONSOLE) ("validate-addon", po::value(), "validate the specified addon's WML against the schema. Requires the user to play the campaign (in the GUI) to trigger the validation.") ("validate-core", "validate the core WML against the schema") - ("validate-schema", po::value(), "validate a specified WML schema") - ("diff,D", po::value()->multitoken(), "diff two preprocessed WML documents") + ("validate-schema", po::value(), "validate a specified WML schema" IMPLY_WCONSOLE) + ("diff,D", po::value()->multitoken(), "diff two preprocessed WML documents" IMPLY_WCONSOLE) ("output,o", po::value(), "output to specified file") - ("patch,P", po::value()->multitoken(), "apply a patch to a preprocessed WML document") - ("preprocess,p", po::value()->multitoken(), "requires two arguments: . Preprocesses a specified file/folder. The preprocessed file(s) will be written in the specified target directory: a plain cfg file and a processed cfg file.") + ("patch,P", po::value()->multitoken(), "apply a patch to a preprocessed WML document" IMPLY_WCONSOLE) + ("preprocess,p", po::value()->multitoken(), "requires two arguments: . Preprocesses a specified file/folder. The preprocessed file(s) will be written in the specified target directory: a plain cfg file and a processed cfg file." IMPLY_WCONSOLE) ("preprocess-defines", po::value(), "comma separated list of defines to be used by '--preprocess' command. If 'SKIP_CORE' is in the define list the data/core won't be preprocessed. Example: --preprocess-defines=FOO,BAR") ("preprocess-input-macros", po::value(), "used only by the '--preprocess' command. Specifies source file that contains [preproc_define]s to be included before preprocessing.") ("preprocess-output-macros", po::value()->implicit_value(std::string()), "used only by the '--preprocess' command. Will output all preprocessed macros in the target file . If the file is not specified the output will be file '_MACROS_.cfg' in the target directory of preprocess's command.") diff --git a/src/log_windows.cpp b/src/log_windows.cpp index ef5ac5c4758e0..79f569dc54bbb 100644 --- a/src/log_windows.cpp +++ b/src/log_windows.cpp @@ -465,12 +465,19 @@ std::string log_file_path() return ""; } -void early_log_file_setup() +static bool disable_redirect; + +void early_log_file_setup(bool disable) { if(lfm) { return; } + if(disable) { + disable_redirect = true; + return; + } + lfm.reset(new log_file_manager()); } @@ -491,8 +498,9 @@ bool using_own_console() void finish_log_file_setup() { + if(disable_redirect) return; // Make sure the LFM is actually set up just in case. - early_log_file_setup(); + early_log_file_setup(false); if(lfm->console_enabled()) { // Nothing to do if running in console mode. diff --git a/src/log_windows.hpp b/src/log_windows.hpp index ed17f8275f7dc..c2d64dd230ce9 100644 --- a/src/log_windows.hpp +++ b/src/log_windows.hpp @@ -57,7 +57,7 @@ std::string log_file_path(); * horribly wrong as soon as we try to use the logging facilities internally * for debug messages. */ -void early_log_file_setup(); +void early_log_file_setup(bool disable); /** * Relocates the stdout+stderr log file to the user data directory. diff --git a/src/wesnoth.cpp b/src/wesnoth.cpp index f2f6365c75f41..62fc12a8b5e56 100644 --- a/src/wesnoth.cpp +++ b/src/wesnoth.cpp @@ -87,6 +87,7 @@ #include // for filtering_stream #include // for error +#include #include // for transform #include // for ENOMEM @@ -973,6 +974,9 @@ int main(int argc, char** argv) } #ifdef _WIN32 + bool log_redirect = true, native_console_implied = false; + // This is optional instead of tribool because value_or() is exactly the required semantic + boost::optional native_console_force; // Some switches force a Windows console to be attached to the process even // if Wesnoth is an IMAGE_SUBSYSTEM_WINDOWS_GUI executable because they // turn it into a CLI application. Also, --wconsole in particular attaches @@ -994,7 +998,7 @@ int main(int argc, char** argv) // care about -- we just want to see if the switch is there. static const std::set wincon_arg_switches = { "-D", "--diff", "-p", "--preprocess", "-P", "--patch", "--render-image", - "--screenshot", "-V", "--validate", "--validate-addon", "--validate-schema", + "--screenshot", "-V", "--validate", "--validate-schema", }; auto switch_matches_arg = [&arg](const std::string& sw) { @@ -1004,12 +1008,22 @@ int main(int argc, char** argv) if(wincon_switches.find(arg) != wincon_switches.end() || std::find_if(wincon_arg_switches.begin(), wincon_arg_switches.end(), switch_matches_arg) != wincon_arg_switches.end()) { - lg::enable_native_console_output(); - break; + native_console_implied = true; + } + + if(arg == "--wnoconsole") { + native_console_force = false; + } else if(arg == "--wconsole") { + native_console_force = true; + } else if(arg == "--wnoredirect") { + log_redirect = false; } } - lg::early_log_file_setup(); + if(native_console_force.value_or(native_console_implied)) { + lg::enable_native_console_output(); + } + lg::early_log_file_setup(!log_redirect); #endif if(SDL_Init(SDL_INIT_TIMER) < 0) {