displayLayout and Rendering TUI library |
git clone git://git.dimitrijedobrota.com/display.git |
Log | Files | Refs | README | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING | |
commit | f025ceaf680e36c28cef477714c94ee94e52f48f |
parent | a218da041827f634ceb1315a75c8547320388d0c |
author | Dimitrije Dobrota <mail@dimitrijedobrota.com> |
date | Sat, 1 Feb 2025 21:27:43 +0100 |
Enter and exit raw mode
Diffstat:M | example/example.cpp | | | ++- |
M | include/display/display.hpp | | | +++++---- |
M | source/display.cpp | | | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- |
3 files changed, 76 insertions(+), 9 deletions(-)
diff --git a/example/example.cpp b/example/example.cpp
@@ -6,7 +6,8 @@ int main()
{
display::start();
(void)std::getchar();
while (true) {
}
display::stop();
diff --git a/include/display/display.hpp b/include/display/display.hpp
@@ -1,11 +1,12 @@
#pragma once
#include "display/display_export.hpp"
namespace display
{
void start();
void stop();
using exit_f = void();
void exit();
void start(exit_f f_exit = exit);
void stop(bool force = false);
} // namespace display
diff --git a/source/display.cpp b/source/display.cpp
@@ -1,20 +1,85 @@
#include <iostream>
#include <stdexcept>
#include "display/display.hpp"
#include <alec/alec.hpp>
#include <termios.h>
#include <unistd.h>
namespace
{
template<const char* Val>
inline void write()
{
::write(STDIN_FILENO, Val, sizeof(Val));
}
} // namespace
namespace display
{
void start()
static int start_count = 0; // NOLINT
static struct termios orig_termios; // NOLINT
void exit()
{
std::cout << alec::abuf_enable_v << alec::cursor_hide_v;
stop(/* force= */ true);
}
void stop()
void start(exit_f f_exit)
{
std::cout << alec::abuf_disable_v;
if (start_count++ > 0) {
// already started
return;
}
if (isatty(STDIN_FILENO) == 0) {
throw std::runtime_error("STDIN_FILENO is not associated with a terminal");
}
if (atexit(f_exit) != 0) {
throw std::runtime_error("Can't register new exit function");
}
if (tcgetattr(STDIN_FILENO, &orig_termios) == -1) {
throw std::runtime_error("Can't read termios");
}
struct termios raw = orig_termios;
// NOLINTBEGIN
raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
raw.c_oflag &= ~(OPOST);
raw.c_cflag |= (CS8);
raw.c_lflag &= ~(ECHO | ICANON | IEXTEN); // | ISIG
raw.c_cc[VMIN] = 0;
raw.c_cc[VTIME] = 1;
// NOLINTEND
/* put terminal in raw mode after flushing */
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) < 0) {
throw std::runtime_error("Can't write termios");
}
write<alec::abuf_enable_v>();
write<alec::cursor_hide_v>();
}
void stop(bool force)
{
if (!force && --start_count > 0) {
// still need to keep open
return;
}
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios) < 0) {
throw std::runtime_error("Can't write termios");
}
write<alec::cursor_show_v>();
}
} // namespace display