2021-08-21 08:29:58 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <atomic>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <mutex>
|
|
|
|
#include <thread>
|
|
|
|
#include <vector>
|
|
|
|
|
2021-08-23 05:22:56 +00:00
|
|
|
#define NOMINMAX
|
2021-08-21 08:29:58 +00:00
|
|
|
#include <windows.h>
|
2021-08-23 05:22:56 +00:00
|
|
|
#undef NOMINMAX
|
2021-08-21 08:29:58 +00:00
|
|
|
|
|
|
|
#include "iConsole.h"
|
|
|
|
|
|
|
|
|
|
|
|
namespace gj {
|
|
|
|
|
|
|
|
|
2021-08-23 05:22:56 +00:00
|
|
|
class Win32Console : public iConsole {
|
2021-08-21 08:29:58 +00:00
|
|
|
public:
|
|
|
|
Win32Console() = delete;
|
|
|
|
Win32Console(Win32Console&&) = delete;
|
|
|
|
Win32Console(const Win32Console&) = delete;
|
|
|
|
|
|
|
|
Win32Console& operator=(Win32Console&&) = delete;
|
|
|
|
Win32Console& operator=(const Win32Console&) = delete;
|
|
|
|
|
|
|
|
Win32Console(iAllocator* alloc, uint32_t w, uint32_t h) :
|
|
|
|
w_(w), h_(h), shown_(false), alive_(true),
|
|
|
|
th_([this]() { main(); }),
|
|
|
|
cb_main_(alloc, w, h), cb_sub_(alloc, w, h),
|
|
|
|
tb_main_(alloc, w, h), tb_sub_(alloc, w, h),
|
|
|
|
chars_(std::make_unique<CHAR_INFO[]>(static_cast<uint64_t>(w)*h)),
|
|
|
|
win_(GetConsoleWindow()) {
|
|
|
|
_ASSERT(win_);
|
|
|
|
|
|
|
|
screen_ = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
|
|
_ASSERT(screen_ != INVALID_HANDLE_VALUE);
|
|
|
|
|
|
|
|
CONSOLE_SCREEN_BUFFER_INFOEX size;
|
|
|
|
size.cbSize = sizeof(size);
|
|
|
|
|
|
|
|
GetConsoleScreenBufferInfoEx(screen_, &size);
|
|
|
|
COORD c;
|
|
|
|
c.X = w_;
|
|
|
|
c.Y = h_;
|
|
|
|
size.dwSize = c;
|
|
|
|
|
|
|
|
size.srWindow.Left = 0;
|
|
|
|
size.srWindow.Right = w_ + 1;
|
|
|
|
size.srWindow.Top = 0;
|
|
|
|
size.srWindow.Bottom = h_ + 1;
|
|
|
|
SetConsoleScreenBufferInfoEx(screen_, &size);
|
|
|
|
|
|
|
|
ShowWindow(win_, FALSE);
|
2021-08-23 09:25:44 +00:00
|
|
|
SetWindowLong(win_, GWL_STYLE, GetWindowLong(win_, GWL_STYLE) & ~(WS_SIZEBOX | WS_MAXIMIZEBOX));
|
2021-08-21 08:29:58 +00:00
|
|
|
}
|
|
|
|
~Win32Console() {
|
|
|
|
alive_.store(false);
|
|
|
|
th_.join();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Show() override {
|
|
|
|
shown_.store(true);
|
|
|
|
}
|
|
|
|
void Hide() override {
|
|
|
|
shown_.store(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
Colorbuffer& TakeColorbuffer() override {
|
|
|
|
return cb_sub_;
|
|
|
|
}
|
|
|
|
void SwapColorbuffer() override {
|
|
|
|
std::lock_guard<std::mutex> _(mtx_);
|
|
|
|
std::swap(cb_main_, cb_sub_);
|
|
|
|
}
|
|
|
|
|
|
|
|
Textbuffer& TakeTextbuffer() override {
|
|
|
|
return tb_sub_;
|
|
|
|
}
|
|
|
|
void SwapTextbuffer() override {
|
|
|
|
std::lock_guard<std::mutex> _(mtx_);
|
|
|
|
std::swap(tb_main_, tb_sub_);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t width() const override {
|
|
|
|
return w_;
|
|
|
|
}
|
|
|
|
uint32_t height() const override {
|
|
|
|
return h_;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
const uint32_t w_, h_;
|
|
|
|
|
|
|
|
std::atomic_bool alive_;
|
|
|
|
std::atomic_bool shown_;
|
|
|
|
std::mutex mtx_;
|
|
|
|
std::thread th_;
|
|
|
|
|
|
|
|
Colorbuffer cb_main_;
|
|
|
|
Colorbuffer cb_sub_;
|
|
|
|
|
|
|
|
Textbuffer tb_main_;
|
|
|
|
Textbuffer tb_sub_;
|
|
|
|
|
|
|
|
std::unique_ptr<CHAR_INFO[]> chars_;
|
|
|
|
|
|
|
|
HANDLE screen_ = INVALID_HANDLE_VALUE;
|
|
|
|
HWND win_ = nullptr;
|
|
|
|
|
|
|
|
void main();
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
}
|