mirror of
https://github.com/mickelson/attract.git
synced 2026-10-12 02:18:55 +00:00
151 lines
4.3 KiB
C++
151 lines
4.3 KiB
C++
// Copyright (c) 2012 Artyom Beilis (Tonkikh)
|
|
// Copyright (c) 2020-2021 Alexander Grund
|
|
//
|
|
// Distributed under the Boost Software License, Version 1.0.
|
|
// https://www.boost.org/LICENSE_1_0.txt
|
|
|
|
#define NOWIDE_SOURCE
|
|
#include <nowide/iostream.hpp>
|
|
|
|
#ifndef NOWIDE_WINDOWS
|
|
|
|
namespace nowide {
|
|
// LCOV_EXCL_START
|
|
/// Avoid empty compilation unit warnings
|
|
/// \internal
|
|
NOWIDE_DECL void dummy_exported_function()
|
|
{}
|
|
// LCOV_EXCL_STOP
|
|
} // namespace nowide
|
|
|
|
#else
|
|
|
|
#include "console_buffer.hpp"
|
|
#include <cassert>
|
|
#include <iostream>
|
|
|
|
#ifndef NOMINMAX
|
|
#define NOMINMAX
|
|
#endif
|
|
#include <windows.h>
|
|
|
|
namespace nowide {
|
|
namespace detail {
|
|
|
|
namespace {
|
|
bool is_atty_handle(HANDLE h)
|
|
{
|
|
DWORD dummy;
|
|
return h && GetConsoleMode(h, &dummy) != FALSE;
|
|
}
|
|
} // namespace
|
|
|
|
class console_output_buffer final : public console_output_buffer_base
|
|
{
|
|
HANDLE handle_;
|
|
|
|
public:
|
|
explicit console_output_buffer(HANDLE handle) : handle_(handle)
|
|
{}
|
|
|
|
protected:
|
|
bool
|
|
do_write(const wchar_t* buffer, std::size_t num_chars_to_write, std::size_t& num_chars_written) override
|
|
{
|
|
DWORD size = 0;
|
|
const bool result =
|
|
WriteConsoleW(handle_, buffer, static_cast<DWORD>(num_chars_to_write), &size, 0) != 0;
|
|
num_chars_written = size;
|
|
return result;
|
|
}
|
|
};
|
|
|
|
class console_input_buffer final : public console_input_buffer_base
|
|
{
|
|
HANDLE handle_;
|
|
|
|
public:
|
|
explicit console_input_buffer(HANDLE handle) : handle_(handle)
|
|
{}
|
|
|
|
protected:
|
|
bool do_read(wchar_t* buffer, std::size_t num_chars_to_read, std::size_t& num_chars_read) override
|
|
{
|
|
DWORD size = 0;
|
|
const auto to_read_size = static_cast<DWORD>(num_chars_to_read);
|
|
const bool result = ReadConsoleW(handle_, buffer, to_read_size, &size, 0) != 0;
|
|
num_chars_read = size;
|
|
return result;
|
|
}
|
|
};
|
|
|
|
winconsole_ostream::winconsole_ostream(const bool isBuffered, winconsole_ostream* tieStream) : std::ostream(0)
|
|
{
|
|
HANDLE h;
|
|
if(isBuffered)
|
|
h = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
else
|
|
h = GetStdHandle(STD_ERROR_HANDLE);
|
|
if(is_atty_handle(h))
|
|
{
|
|
d.reset(new console_output_buffer(h));
|
|
std::ostream::rdbuf(d.get());
|
|
} else
|
|
{
|
|
std::ostream::rdbuf(isBuffered ? std::cout.rdbuf() : std::cerr.rdbuf());
|
|
assert(rdbuf());
|
|
}
|
|
if(tieStream)
|
|
{
|
|
tie(tieStream);
|
|
setf(ios_base::unitbuf); // If tieStream is set, this is cerr -> set unbuffered
|
|
}
|
|
}
|
|
winconsole_ostream::~winconsole_ostream()
|
|
{
|
|
try
|
|
{
|
|
flush();
|
|
} catch(...)
|
|
{} // LCOV_EXCL_LINE
|
|
}
|
|
|
|
winconsole_istream::winconsole_istream(winconsole_ostream* tieStream) : std::istream(0)
|
|
{
|
|
HANDLE h = GetStdHandle(STD_INPUT_HANDLE);
|
|
if(is_atty_handle(h))
|
|
{
|
|
d.reset(new console_input_buffer(h));
|
|
std::istream::rdbuf(d.get());
|
|
} else
|
|
{
|
|
std::istream::rdbuf(std::cin.rdbuf());
|
|
assert(rdbuf());
|
|
}
|
|
if(tieStream)
|
|
tie(tieStream);
|
|
}
|
|
|
|
winconsole_istream::~winconsole_istream()
|
|
{}
|
|
|
|
} // namespace detail
|
|
|
|
// Make sure those are initialized as early as possible
|
|
#ifdef NOWIDE_MSVC
|
|
#pragma warning(disable : 4073)
|
|
#pragma init_seg(lib)
|
|
#endif
|
|
#ifdef NOWIDE_HAS_INIT_PRIORITY
|
|
#define NOWIDE_INIT_PRIORITY __attribute__((init_priority(101)))
|
|
#else
|
|
#define NOWIDE_INIT_PRIORITY
|
|
#endif
|
|
detail::winconsole_ostream cout NOWIDE_INIT_PRIORITY(true, nullptr);
|
|
detail::winconsole_istream cin NOWIDE_INIT_PRIORITY(&cout);
|
|
detail::winconsole_ostream cerr NOWIDE_INIT_PRIORITY(false, &cout);
|
|
detail::winconsole_ostream clog NOWIDE_INIT_PRIORITY(false, nullptr);
|
|
} // namespace nowide
|
|
|
|
#endif
|