Add single codepoint unicode character support
This commit is contained in:
parent
d6db7301f0
commit
2210bf7d69
@ -14,14 +14,21 @@ typedef void (*terml_resize_callback)(
|
|||||||
unsigned int previous_height
|
unsigned int previous_height
|
||||||
);
|
);
|
||||||
|
|
||||||
|
struct tcell
|
||||||
|
{
|
||||||
|
int codepoint;
|
||||||
|
int foreground;
|
||||||
|
int background;
|
||||||
|
};
|
||||||
|
|
||||||
int terml_init();
|
int terml_init();
|
||||||
int terml_deinit();
|
int terml_deinit();
|
||||||
|
|
||||||
unsigned int terml_get_width();
|
unsigned int terml_get_width();
|
||||||
unsigned int terml_get_height();
|
unsigned int terml_get_height();
|
||||||
|
|
||||||
char terml_get(unsigned int x, unsigned int y, int* foreground_color, int* background_color);
|
int terml_get(unsigned int x, unsigned int y, const tcell** cell);
|
||||||
void terml_set(unsigned int x, unsigned int y, char c, int foreground_color, int background_color);
|
int terml_set(unsigned int x, unsigned int y, tcell cell);
|
||||||
void terml_flush();
|
void terml_flush();
|
||||||
|
|
||||||
void terml_set_main_callback(terml_main_callback);
|
void terml_set_main_callback(terml_main_callback);
|
||||||
|
248
source/terml.cpp
248
source/terml.cpp
@ -9,108 +9,102 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
constexpr int BYTE_ONE_MASK = 0b0000'0000'0000'0000'0011'1111;
|
||||||
|
constexpr int BYTE_TWO_MASK = 0b0000'0000'0000'1111'1100'0000;
|
||||||
|
constexpr int BYTE_THREE_MASK = 0b0000'0011'1111'0000'0000'0000;
|
||||||
|
constexpr int BYTE_FOUR_MASK = 0b0001'1100'0000'0000'0000'0000;
|
||||||
|
|
||||||
|
constexpr int BYTE_ONE_MASK_OFFSET = 0;
|
||||||
|
constexpr int BYTE_TWO_MASK_OFFSET = BYTE_ONE_MASK_OFFSET + 2;
|
||||||
|
constexpr int BYTE_THREE_MASK_OFFSET = BYTE_TWO_MASK_OFFSET + 2;
|
||||||
|
constexpr int BYTE_FOUR_MASK_OFFSET = BYTE_THREE_MASK_OFFSET + 2;
|
||||||
|
|
||||||
|
constexpr int ONE_BYTE_FILL = 0b10000000;
|
||||||
|
constexpr int TWO_BYTE_FILL = 0b11000000'10000000;
|
||||||
|
constexpr int THREE_BYTE_FILL = 0b11100000'10000000'10000000;
|
||||||
|
constexpr int FOUR_BYTE_FILL = 0b11110000'10000000'10000000'10000000;
|
||||||
|
|
||||||
|
void print_cell(tcell cell, const tcell* last)
|
||||||
|
{
|
||||||
|
if (!last || cell.foreground != last->foreground)
|
||||||
|
{
|
||||||
|
printf(FGP, (cell.foreground & 0xFF0000) >> 16, (cell.foreground & 0xFF00) >> 8, cell.foreground & 0xFF);
|
||||||
|
}
|
||||||
|
if (!last || cell.background != last->background)
|
||||||
|
{
|
||||||
|
printf(BGP, (cell.background & 0xFF0000) >> 16, (cell.background & 0xFF00) >> 8, cell.background & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// one-byte codepoints
|
||||||
|
if (cell.codepoint < 0x80)
|
||||||
|
{
|
||||||
|
const char str[] = { cell.codepoint, '\0' };
|
||||||
|
printf("%s", str);
|
||||||
|
}
|
||||||
|
// two-byte codepoints
|
||||||
|
else if (cell.codepoint < 0x800)
|
||||||
|
{
|
||||||
|
const int byte_one = (cell.codepoint & BYTE_ONE_MASK) << BYTE_ONE_MASK_OFFSET;
|
||||||
|
const int byte_two = (cell.codepoint & BYTE_TWO_MASK) << BYTE_TWO_MASK_OFFSET;
|
||||||
|
const int utf8 = TWO_BYTE_FILL | byte_one | byte_two;
|
||||||
|
|
||||||
|
const char str[] = { (utf8 & 0xFF00) >> 8, utf8 & 0xFF, '\0' };
|
||||||
|
printf("%s", str);
|
||||||
|
}
|
||||||
|
// three-byte codepoints
|
||||||
|
else if (cell.codepoint < 0x10000)
|
||||||
|
{
|
||||||
|
const int byte_one = (cell.codepoint & BYTE_ONE_MASK) << BYTE_ONE_MASK_OFFSET;
|
||||||
|
const int byte_two = (cell.codepoint & BYTE_TWO_MASK) << BYTE_TWO_MASK_OFFSET;
|
||||||
|
const int byte_three = (cell.codepoint & BYTE_THREE_MASK) << BYTE_THREE_MASK_OFFSET;
|
||||||
|
const int utf8 = THREE_BYTE_FILL | byte_one | byte_two | byte_three;
|
||||||
|
|
||||||
|
const char str[] = { (utf8 & 0xFF0000) >> 16, (utf8 & 0xFF00) >> 8, utf8 & 0xFF, '\0' };
|
||||||
|
printf("%s", str);
|
||||||
|
}
|
||||||
|
// four-byte codepoints
|
||||||
|
else if (cell.codepoint < 0x110000)
|
||||||
|
{
|
||||||
|
const int byte_one = (cell.codepoint & BYTE_ONE_MASK) << BYTE_ONE_MASK_OFFSET;
|
||||||
|
const int byte_two = (cell.codepoint & BYTE_TWO_MASK) << BYTE_TWO_MASK_OFFSET;
|
||||||
|
const int byte_three = (cell.codepoint & BYTE_THREE_MASK) << BYTE_THREE_MASK_OFFSET;
|
||||||
|
const int byte_four = (cell.codepoint & BYTE_FOUR_MASK) << BYTE_FOUR_MASK_OFFSET;
|
||||||
|
const int utf8 = FOUR_BYTE_FILL | byte_one | byte_two | byte_three | byte_four;
|
||||||
|
|
||||||
|
const char str[] = { (utf8 & 0xFF000000) >> 24, (utf8 & 0xFF0000) >> 16, (utf8 & 0xFF00) >> 8, utf8 & 0xFF, '\0' };
|
||||||
|
printf("%s", str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
terml::terml() :
|
terml::terml() :
|
||||||
|
cells(nullptr),
|
||||||
|
width(0),
|
||||||
|
height(0),
|
||||||
main(nullptr),
|
main(nullptr),
|
||||||
quit(nullptr),
|
quit(nullptr),
|
||||||
key(nullptr),
|
key(nullptr),
|
||||||
resize(nullptr),
|
resize(nullptr),
|
||||||
buffer(nullptr),
|
should_quit(false),
|
||||||
width(0),
|
really_should_quit(false)
|
||||||
height(0)
|
|
||||||
{
|
{
|
||||||
printf(ALT_BUF() HIDE_CURSOR());
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
terml::~terml()
|
terml::~terml()
|
||||||
{
|
{
|
||||||
printf(REG_BUF() SHOW_CURSOR());
|
if (cells) { delete[] cells; }
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
delete[] buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char terml::get(unsigned int x, unsigned int y, int* fg, int* bg) const
|
const tcell& terml::get(unsigned int x, unsigned int y) const
|
||||||
{
|
{
|
||||||
const unsigned int offset = x + y * width;
|
return cells[x + y * width];
|
||||||
|
|
||||||
if (fg)
|
|
||||||
{
|
|
||||||
const unsigned char r =
|
|
||||||
(buffer[offset * CELL_SIZE + 9] - '0') +
|
|
||||||
(buffer[offset * CELL_SIZE + 8] - '0') * 10 +
|
|
||||||
(buffer[offset * CELL_SIZE + 7] - '0') * 100;
|
|
||||||
|
|
||||||
const unsigned char g =
|
|
||||||
(buffer[offset * CELL_SIZE + 13] - '0') +
|
|
||||||
(buffer[offset * CELL_SIZE + 12] - '0') * 10 +
|
|
||||||
(buffer[offset * CELL_SIZE + 11] - '0') * 100;
|
|
||||||
|
|
||||||
const unsigned char b =
|
|
||||||
(buffer[offset * CELL_SIZE + 17] - '0') +
|
|
||||||
(buffer[offset * CELL_SIZE + 16] - '0') * 10 +
|
|
||||||
(buffer[offset * CELL_SIZE + 15] - '0') * 100;
|
|
||||||
|
|
||||||
*fg = (r << 16) | (g << 8) | b;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bg)
|
|
||||||
{
|
|
||||||
const unsigned char r =
|
|
||||||
(buffer[offset * CELL_SIZE + 28] - '0') +
|
|
||||||
(buffer[offset * CELL_SIZE + 27] - '0') * 10 +
|
|
||||||
(buffer[offset * CELL_SIZE + 26] - '0') * 100;
|
|
||||||
|
|
||||||
const unsigned char g =
|
|
||||||
(buffer[offset * CELL_SIZE + 32] - '0') +
|
|
||||||
(buffer[offset * CELL_SIZE + 31] - '0') * 10 +
|
|
||||||
(buffer[offset * CELL_SIZE + 30] - '0') * 100;
|
|
||||||
|
|
||||||
const unsigned char b =
|
|
||||||
(buffer[offset * CELL_SIZE + 36] - '0') +
|
|
||||||
(buffer[offset * CELL_SIZE + 35] - '0') * 10 +
|
|
||||||
(buffer[offset * CELL_SIZE + 34] - '0') * 100;
|
|
||||||
|
|
||||||
*bg = (r << 16) | (g << 8) | b;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer[offset * CELL_SIZE + CELL_SIZE - 1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void terml::set(unsigned int x, unsigned int y, char c, int fg, int bg)
|
void terml::set(unsigned int x, unsigned int y, tcell cell)
|
||||||
{
|
{
|
||||||
const unsigned int offset = x + y * width;
|
cells[x + y * width] = cell;
|
||||||
|
|
||||||
unsigned char fgr = (fg & 0xFF0000) >> 16;
|
|
||||||
unsigned char fgg = (fg & 0x00FF00) >> 8;
|
|
||||||
unsigned char fgb = (fg & 0x0000FF);
|
|
||||||
|
|
||||||
unsigned char bgr = (bg & 0xFF0000) >> 16;
|
|
||||||
unsigned char bgg = (bg & 0x00FF00) >> 8;
|
|
||||||
unsigned char bgb = (bg & 0x0000FF);
|
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++)
|
|
||||||
{
|
|
||||||
buffer[offset * CELL_SIZE + (9 - i)] = (fgr % 10) + '0';
|
|
||||||
fgr /= 10;
|
|
||||||
|
|
||||||
buffer[offset * CELL_SIZE + (13 - i)] = (fgg % 10) + '0';
|
|
||||||
fgg /= 10;
|
|
||||||
|
|
||||||
buffer[offset * CELL_SIZE + (17 - i)] = (fgb % 10) + '0';
|
|
||||||
fgb /= 10;
|
|
||||||
|
|
||||||
buffer[offset * CELL_SIZE + (28 - i)] = (bgr % 10) + '0';
|
|
||||||
bgr /= 10;
|
|
||||||
|
|
||||||
buffer[offset * CELL_SIZE + (32 - i)] = (bgg % 10) + '0';
|
|
||||||
bgg /= 10;
|
|
||||||
|
|
||||||
buffer[offset * CELL_SIZE + (36 - i)] = (bgb % 10) + '0';
|
|
||||||
bgb /= 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer[offset * CELL_SIZE + CELL_SIZE - 1] = c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void terml::flush() const
|
void terml::flush() const
|
||||||
@ -118,7 +112,11 @@ void terml::flush() const
|
|||||||
printf(CUP(1, 1));
|
printf(CUP(1, 1));
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
printf("%s", buffer);
|
print_cell(cells[0], nullptr);
|
||||||
|
for (int i = 1; i < width * height; i++)
|
||||||
|
{
|
||||||
|
print_cell(cells[i], &cells[i - 1]);
|
||||||
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,7 +153,7 @@ void terml::mainloop()
|
|||||||
should_quit = false;
|
should_quit = false;
|
||||||
really_should_quit = false;
|
really_should_quit = false;
|
||||||
|
|
||||||
const unsigned long long wait_time = timer_frequency() / 1000;
|
const unsigned long long wait_time = timer_frequency() / 60;
|
||||||
unsigned long long last_time = timer();
|
unsigned long long last_time = timer();
|
||||||
|
|
||||||
while (!really_should_quit)
|
while (!really_should_quit)
|
||||||
@ -230,17 +228,9 @@ void terml::setup_buffer()
|
|||||||
width = new_width;
|
width = new_width;
|
||||||
height = new_height;
|
height = new_height;
|
||||||
|
|
||||||
if (buffer) { delete[] buffer; }
|
if (cells) { delete[] cells; }
|
||||||
buffer = new char[CELL_SIZE * width * height + 1];
|
cells = new tcell[width * height];
|
||||||
|
memset(cells, 0, sizeof(tcell) * width * height);
|
||||||
constexpr char BLANK_CELL[] = FG(255, 255, 255) CSI "48;2;000;000;000m" " ";
|
|
||||||
|
|
||||||
for (int i = 0; i < width * height; i++)
|
|
||||||
{
|
|
||||||
memcpy(buffer + i * CELL_SIZE, BLANK_CELL, CELL_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer[CELL_SIZE * width * height] = '\0';
|
|
||||||
|
|
||||||
if (resize)
|
if (resize)
|
||||||
{
|
{
|
||||||
@ -249,6 +239,23 @@ void terml::setup_buffer()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void terml::set_console_settings()
|
||||||
|
{
|
||||||
|
setvbuf(stdout, nullptr, _IOFBF, BUFSIZ * BUFSIZ);
|
||||||
|
printf(ALT_BUF() HIDE_CURSOR());
|
||||||
|
fflush(stdout);
|
||||||
|
set_console_settings_impl();
|
||||||
|
}
|
||||||
|
|
||||||
|
void terml::reset_console_settings()
|
||||||
|
{
|
||||||
|
setvbuf(stdout, nullptr, _IOLBF, BUFSIZ);
|
||||||
|
printf(REG_BUF() SHOW_CURSOR());
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
reset_console_settings_impl();
|
||||||
|
}
|
||||||
|
|
||||||
static terml* TERML_G;
|
static terml* TERML_G;
|
||||||
static const char* LAST_ERROR = nullptr;
|
static const char* LAST_ERROR = nullptr;
|
||||||
|
|
||||||
@ -266,16 +273,20 @@ extern "C"
|
|||||||
TERML_G = new terml_linux;
|
TERML_G = new terml_linux;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw "terml already initialized.";
|
||||||
|
}
|
||||||
|
|
||||||
TERML_G->set_console_settings();
|
TERML_G->set_console_settings();
|
||||||
TERML_G->setup_buffer();
|
TERML_G->setup_buffer();
|
||||||
|
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
catch (const char* c)
|
catch (const char* c)
|
||||||
{
|
{
|
||||||
LAST_ERROR = c;
|
LAST_ERROR = c;
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,12 +300,12 @@ extern "C"
|
|||||||
delete TERML_G;
|
delete TERML_G;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
catch (const char* c)
|
catch (const char* c)
|
||||||
{
|
{
|
||||||
LAST_ERROR = c;
|
LAST_ERROR = c;
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,14 +319,37 @@ extern "C"
|
|||||||
return TERML_G->get_height();
|
return TERML_G->get_height();
|
||||||
}
|
}
|
||||||
|
|
||||||
char terml_get(unsigned int x, unsigned int y, int* fg, int* bg)
|
int terml_get(unsigned int x, unsigned int y, const tcell** cell)
|
||||||
{
|
{
|
||||||
return TERML_G->get(x, y, fg, bg);
|
if (x >= TERML_G->get_width() || y >= TERML_G->get_height())
|
||||||
|
{
|
||||||
|
LAST_ERROR = "Coordinates out of bounds.";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (!cell)
|
||||||
|
{
|
||||||
|
LAST_ERROR = "Null output pointer.";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*cell = &TERML_G->get(x, y);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void terml_set(unsigned int x, unsigned int y, char c, int fg, int bg)
|
int terml_set(unsigned int x, unsigned int y, tcell cell)
|
||||||
{
|
{
|
||||||
TERML_G->set(x, y, c, fg, bg);
|
if (x >= TERML_G->get_width() || y >= TERML_G->get_height())
|
||||||
|
{
|
||||||
|
LAST_ERROR = "Coordinates out of bounds.";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TERML_G->set(x, y, cell);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void terml_flush()
|
void terml_flush()
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
|
||||||
void terml_linux::set_console_settings()
|
void terml_linux::set_console_settings_impl()
|
||||||
{
|
{
|
||||||
tcgetattr(STDIN_FILENO, &old_input_settings);
|
tcgetattr(STDIN_FILENO, &old_input_settings);
|
||||||
tcgetattr(STDOUT_FILENO, &old_output_settings);
|
tcgetattr(STDOUT_FILENO, &old_output_settings);
|
||||||
@ -18,7 +18,7 @@ void terml_linux::set_console_settings()
|
|||||||
tcsetattr(STDIN_FILENO, TCSANOW, &t);
|
tcsetattr(STDIN_FILENO, TCSANOW, &t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void terml_linux::reset_console_settings()
|
void terml_linux::reset_console_settings_impl()
|
||||||
{
|
{
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, &old_input_settings);
|
tcsetattr(STDIN_FILENO, TCSANOW, &old_input_settings);
|
||||||
tcsetattr(STDOUT_FILENO, TCSANOW, &old_output_settings);
|
tcsetattr(STDOUT_FILENO, TCSANOW, &old_output_settings);
|
||||||
|
@ -11,8 +11,8 @@
|
|||||||
class terml_linux : public terml
|
class terml_linux : public terml
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
virtual void set_console_settings() override;
|
virtual void set_console_settings_impl() override;
|
||||||
virtual void reset_console_settings() override;
|
virtual void reset_console_settings_impl() override;
|
||||||
virtual void read_stdin(char* buffer, unsigned int buffer_size) override;
|
virtual void read_stdin(char* buffer, unsigned int buffer_size) override;
|
||||||
virtual unsigned long long timer() override;
|
virtual unsigned long long timer() override;
|
||||||
virtual unsigned long long timer_frequency() override;
|
virtual unsigned long long timer_frequency() override;
|
||||||
|
@ -25,6 +25,9 @@
|
|||||||
#define FG(r, g, b) CSI "38;2;" STRINGIFY(r) ";" STRINGIFY(g) ";" STRINGIFY(b) "m"
|
#define FG(r, g, b) CSI "38;2;" STRINGIFY(r) ";" STRINGIFY(g) ";" STRINGIFY(b) "m"
|
||||||
#define BG(r, g, b) CSI "48;2;" STRINGIFY(r) ";" STRINGIFY(g) ";" STRINGIFY(b) "m"
|
#define BG(r, g, b) CSI "48;2;" STRINGIFY(r) ";" STRINGIFY(g) ";" STRINGIFY(b) "m"
|
||||||
|
|
||||||
|
#define FGP CSI "38;2;%d;%d;%dm"
|
||||||
|
#define BGP CSI "48;2;%d;%d;%dm"
|
||||||
|
|
||||||
class terml
|
class terml
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -37,8 +40,8 @@ public:
|
|||||||
terml& operator=(const terml&) = delete;
|
terml& operator=(const terml&) = delete;
|
||||||
terml& operator=(terml&&) = delete;
|
terml& operator=(terml&&) = delete;
|
||||||
|
|
||||||
char get(unsigned int x, unsigned int y, int* fg, int* bg) const;
|
const tcell& get(unsigned int x, unsigned int y) const;
|
||||||
void set(unsigned int x, unsigned int y, char c, int fg, int bg);
|
void set(unsigned int x, unsigned int y, tcell cell);
|
||||||
void flush() const;
|
void flush() const;
|
||||||
|
|
||||||
void set_main_callback(terml_main_callback);
|
void set_main_callback(terml_main_callback);
|
||||||
@ -54,10 +57,12 @@ public:
|
|||||||
|
|
||||||
void setup_buffer();
|
void setup_buffer();
|
||||||
|
|
||||||
virtual void set_console_settings() = 0;
|
void set_console_settings();
|
||||||
virtual void reset_console_settings() = 0;
|
void reset_console_settings();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual void set_console_settings_impl() = 0;
|
||||||
|
virtual void reset_console_settings_impl() = 0;
|
||||||
virtual void read_stdin(char* buffer, unsigned int buffer_size) = 0;
|
virtual void read_stdin(char* buffer, unsigned int buffer_size) = 0;
|
||||||
virtual unsigned long long timer() = 0;
|
virtual unsigned long long timer() = 0;
|
||||||
virtual unsigned long long timer_frequency() = 0;
|
virtual unsigned long long timer_frequency() = 0;
|
||||||
@ -66,7 +71,7 @@ protected:
|
|||||||
void key_event(char code) const;
|
void key_event(char code) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char* buffer;
|
tcell* cells;
|
||||||
unsigned int width;
|
unsigned int width;
|
||||||
unsigned int height;
|
unsigned int height;
|
||||||
terml_main_callback main;
|
terml_main_callback main;
|
||||||
@ -75,8 +80,6 @@ private:
|
|||||||
terml_resize_callback resize;
|
terml_resize_callback resize;
|
||||||
bool should_quit;
|
bool should_quit;
|
||||||
bool really_should_quit;
|
bool really_should_quit;
|
||||||
|
|
||||||
static const unsigned int CELL_SIZE = sizeof(FG(255, 255, 255) BG(255, 255, 255) " ") - 1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif//TERML_TERML_PRIVATE_H
|
#endif//TERML_TERML_PRIVATE_H
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|
||||||
void terml_windows::set_console_settings()
|
void terml_windows::set_console_settings_impl()
|
||||||
{
|
{
|
||||||
handle_stdin = GetStdHandle(STD_INPUT_HANDLE);
|
handle_stdin = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
GetConsoleMode(handle_stdin, &previous_input_mode);
|
GetConsoleMode(handle_stdin, &previous_input_mode);
|
||||||
@ -13,7 +13,7 @@ void terml_windows::set_console_settings()
|
|||||||
new_mode |= ENABLE_VIRTUAL_TERMINAL_INPUT;
|
new_mode |= ENABLE_VIRTUAL_TERMINAL_INPUT;
|
||||||
if (!SetConsoleMode(handle_stdin, new_mode))
|
if (!SetConsoleMode(handle_stdin, new_mode))
|
||||||
{
|
{
|
||||||
throw "Failed to set stdin mode";
|
throw "Failed to set stdin mode.";
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
@ -23,19 +23,27 @@ void terml_windows::set_console_settings()
|
|||||||
new_mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
new_mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||||
if (!SetConsoleMode(handle, new_mode))
|
if (!SetConsoleMode(handle, new_mode))
|
||||||
{
|
{
|
||||||
throw "Failed to set stdout mode";
|
throw "Failed to set stdout mode.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
previous_codepage = GetConsoleOutputCP();
|
||||||
|
SetConsoleOutputCP(CP_UTF8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void terml_windows::reset_console_settings()
|
void terml_windows::reset_console_settings_impl()
|
||||||
{
|
{
|
||||||
if (!SetConsoleMode(handle_stdin, previous_input_mode))
|
if (!SetConsoleMode(handle_stdin, previous_input_mode))
|
||||||
{
|
{
|
||||||
throw "Failed to reset stdin mode";
|
throw "Failed to reset stdin mode.";
|
||||||
}
|
}
|
||||||
if (!SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), previous_output_mode))
|
if (!SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), previous_output_mode))
|
||||||
{
|
{
|
||||||
throw "Failed to reset stdout mode";
|
throw "Failed to reset stdout mode.";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!SetConsoleOutputCP(previous_codepage))
|
||||||
|
{
|
||||||
|
throw "Failed to reset codepage.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,8 +11,8 @@
|
|||||||
class terml_windows : public terml
|
class terml_windows : public terml
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
virtual void set_console_settings() override;
|
virtual void set_console_settings_impl() override;
|
||||||
virtual void reset_console_settings() override;
|
virtual void reset_console_settings_impl() override;
|
||||||
virtual void read_stdin(char* buffer, unsigned int buffer_size) override;
|
virtual void read_stdin(char* buffer, unsigned int buffer_size) override;
|
||||||
virtual unsigned long long timer() override;
|
virtual unsigned long long timer() override;
|
||||||
virtual unsigned long long timer_frequency() override;
|
virtual unsigned long long timer_frequency() override;
|
||||||
@ -21,6 +21,7 @@ protected:
|
|||||||
private:
|
private:
|
||||||
DWORD previous_input_mode;
|
DWORD previous_input_mode;
|
||||||
DWORD previous_output_mode;
|
DWORD previous_output_mode;
|
||||||
|
UINT previous_codepage;
|
||||||
HANDLE handle_stdin;
|
HANDLE handle_stdin;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user