Add --wconsole for allocating a Windows console on startup

This is only recognized by the game client at the moment. The
implementation is a bit hacky but it seems to work. Thanks, SDLmain.

The cwesnoth.cmd Windows batch file passes --wconsole to Wesnoth in the
command line, along with any other arguments passed to it. This is
intended to be *the* use case for --wconsole, since otherwise the fact
that Windows won't allocate a console for us on process initialization
(due to Wesnoth being compiled with the GUI application flag) causes
issues with the Command Prompt shell -- namely, the shell returns
before Wesnoth allocates its console, allowing shell input to happen
concurrently with Wesnoth's output to console.

cwesnoth.cmd should be used in shortcuts and given Wesnoth's install
path as its initial working directory.
This commit is contained in:
Ignacio R. Morelle 2015-04-25 04:31:41 -04:00
parent 4f227059cf
commit 8d2609ff4c
8 changed files with 150 additions and 3 deletions

1
cwesnoth.cmd Normal file
View file

@ -0,0 +1 @@
@wesnoth --wconsole %*

View file

@ -233,6 +233,8 @@
<Unit filename="../../src/desktop/notifications.hpp" />
<Unit filename="../../src/desktop/open.cpp" />
<Unit filename="../../src/desktop/open.hpp" />
<Unit filename="../../src/desktop/windows_console.cpp" />
<Unit filename="../../src/desktop/windows_console.hpp" />
<Unit filename="../../src/desktop/windows_tray_notification.cpp" />
<Unit filename="../../src/desktop/windows_tray_notification.hpp" />
<Unit filename="../../src/dialogs.cpp" />

View file

@ -1095,6 +1095,7 @@ set(libwesnoth-game_STAT_SRC
if(WIN32)
set(libwesnoth-game_STAT_SRC
${libwesnoth-game_STAT_SRC}
desktop/windows_console.cpp
desktop/windows_tray_notification.cpp
)
endif(WIN32)

View file

@ -615,6 +615,7 @@ wesnoth_sources = Split("""
if env["PLATFORM"] == "win32":
wesnoth_sources.append("desktop/windows_tray_notification.cpp")
wesnoth_sources.append("desktop/windows_console.cpp")
if env["PLATFORM"] == 'darwin':
wesnoth_sources.append("desktop/apple_notification.mm")

View file

@ -201,6 +201,9 @@ commandline_options::commandline_options (const std::vector<std::string>& args)
("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)")
#endif // _WIN32
;
po::options_description campaign_opts("Campaign options");

View file

@ -0,0 +1,96 @@
/*
Copyright (C) 2014 - 2015 by Ignacio Riquelme Morelle <shadowm2006@gmail.com>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#include "desktop/windows_console.hpp"
#include "log.hpp"
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x0501 // XP and later
#include <windows.h>
#include <cstdio>
#include <boost/scoped_ptr.hpp>
static lg::log_domain log_desktop("desktop");
#define ERR_DU LOG_STREAM(err, log_desktop)
#define LOG_DU LOG_STREAM(info, log_desktop)
namespace {
class win32_console_manager
{
public:
win32_console_manager()
{
#if 0
// Because this runs before cmdline processing, enable this block for
// debugging purposes if necessary.
lg::set_log_domain_severity("desktop", lg::debug);
#endif
if(AttachConsole(ATTACH_PARENT_PROCESS)) {
LOG_DU << "win32_console: attached to parent process console\n";
} else if(AllocConsole()) {
LOG_DU << "win32_console: attached to own console\n";
} else {
ERR_DU << "win32_console: failed to attach or allocate console!";
return;
}
LOG_DU << "win32_console: stdin to console\n";
freopen("CONIN$", "rb", stdin);
LOG_DU << "win32_console: stdout to console\n";
std::cout.flush();
freopen("CONOUT$", "wb", stdout);
LOG_DU << "win32_console: stderr to console\n";
std::cerr.flush();
freopen("CONOUT$", "wb", stderr);
LOG_DU << "win32_console: init complete\n";
}
~win32_console_manager()
{
FreeConsole();
LOG_DU << "win32_console: uninit complete\n";
}
};
boost::scoped_ptr<win32_console_manager> conman;
} // end anonymous namespace
namespace desktop {
void enable_win32_console()
{
if(!conman) {
conman.reset(new win32_console_manager());
} else {
ERR_DU << "win32_console: Console already enabled!\n";
}
}
void disable_win32_console()
{
conman.reset(NULL);
}
} // end namespace desktop

View file

@ -0,0 +1,27 @@
/*
Copyright (C) 2014 - 2015 by Ignacio Riquelme Morelle <shadowm2006@gmail.com>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#ifndef DESKTOP_WIN32_CONSOLE_HPP_INCLUDED
#define DESKTOP_WIN32_CONSOLE_HPP_INCLUDED
namespace desktop {
void enable_win32_console();
void disable_win32_console();
}
#endif // DESKTOP_WIN32_CONSOLE_HPP_INCLUDED

View file

@ -61,6 +61,10 @@
#include "widgets/button.hpp" // for button
#include "wml_exception.hpp" // for twml_exception
#ifdef _WIN32
#include "desktop/windows_console.hpp"
#endif // _WIN32
#include <SDL.h> // for SDL_Init, SDL_INIT_TIMER
#include <boost/foreach.hpp> // for auto_any_base, etc
#include <boost/iostreams/categories.hpp> // for input, output
@ -862,11 +866,11 @@ static bool parse_commandline_argument(const char*& next, const char* end, std::
else if(*next == '"' && is_excaped && next + 1 != end && *(next + 1) == '"') {
res.push_back('"');
++next;
continue;
continue;
}
else if(*next == '"' && is_excaped ) {
is_excaped = false;
continue;
continue;
}
else {
res.push_back(*next);
@ -881,7 +885,7 @@ static std::vector<std::string> parse_commandline_arguments(std::string input)
const char* end = start + input.size();
std::string buffer;
std::vector<std::string> res;
while(parse_commandline_argument(start, end, buffer))
{
res.push_back(std::string());
@ -931,8 +935,20 @@ int main(int argc, char** argv)
#ifdef _WIN32
(void)argc;
(void)argv;
//windows argv is ansi encoded by default
std::vector<std::string> args = parse_commandline_arguments(unicode_cast<std::string>(std::wstring(GetCommandLineW())));
// HACK: we don't parse command line arguments using program_options until
// the startup banner is printed. We need to get a console up and
// running before then if requested, so just perform a trivial search
// here and let program_options ignore the switch later.
for(size_t k = 0; k < args.size(); ++k) {
if(args[k] == "--wconsole") {
desktop::enable_win32_console();
break;
}
}
#else
std::vector<std::string> args;
for(int i = 0; i < argc; ++i)