Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 34 additions & 12 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,14 @@ option(CPPTERMINAL_ENABLE_TESING "Set to ON to enable testing" ON)

set(CMAKE_POSITION_INDEPENDENT_CODE ON)

add_library(cpp-terminal INTERFACE)
add_library(cpp-terminal cpp-terminal/terminal_base.cpp)
target_include_directories(cpp-terminal BEFORE PUBLIC
${cpp-terminal_SOURCE_DIR})
target_include_directories(cpp-terminal INTERFACE ${PROJECT_SOURCE_DIR} ${PROJECT_BINARY_DIR})
set_target_properties(cpp-terminal PROPERTIES
PUBLIC_HEADER "cpp-terminal/terminal.h;cpp-terminal/terminal_base.h;cpp-terminal/version.h"
)

set(CPPTERMINAL_CMAKECONFIG_INCLUDE_DIR "include" CACHE STRING "install include directory")
include(CMakePackageConfigHelpers)
configure_package_config_file(${PROJECT_NAME}Config.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
INSTALL_DESTINATION lib/${PROJECT_NAME}/cmake
PATH_VARS CPPTERMINAL_CMAKECONFIG_INCLUDE_DIR)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
DESTINATION lib/${PROJECT_NAME}/cmake )


if (CPPTERMINAL_ENABLE_TESING)
enable_testing()
add_subdirectory(tests)
Expand All @@ -44,10 +36,40 @@ if (CPPTERMINAL_BUILD_EXAMPLES)
endif()

if (CPPTERMINAL_ENABLE_INSTALL)
install(TARGETS cpp-terminal
install(TARGETS cpp-terminal EXPORT cpp-terminalTargets
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
PUBLIC_HEADER DESTINATION include/cpp-terminal
)

include(CMakePackageConfigHelpers)

write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/cpp-terminal/cpp-terminalConfigVersion.cmake"
VERSION ${CPPTERMINAL_VERSION}
COMPATIBILITY AnyNewerVersion
)

export(EXPORT cpp-terminalTargets
FILE "${CMAKE_CURRENT_BINARY_DIR}/cpp-terminal/cpp-terminalTargets.cmake"
)

set(ConfigPackageLocation lib/cmake/cpp-terminal)

configure_file(cpp-terminalConfig.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/cpp-terminal/cpp-terminalConfig.cmake"
)

install(
FILES
"${CMAKE_CURRENT_BINARY_DIR}/cpp-terminal/cpp-terminalConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/cpp-terminal/cpp-terminalConfigVersion.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/cpp-terminal/cpp-terminalTargets.cmake"
DESTINATION
${ConfigPackageLocation}
COMPONENT
Devel
)

endif()
82 changes: 82 additions & 0 deletions cpp-terminal/terminal_base.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#include <cpp-terminal/terminal_base.h>

namespace Term {

#ifdef _WIN32
BaseTerminal::BaseTerminal(bool enable_keyboard,
bool /*disable_ctrl_c*/)
: keyboard_enabled{enable_keyboard} {
// Uncomment this to silently disable raw mode for non-tty
// if (keyboard_enabled) keyboard_enabled = is_stdin_a_tty();
out_console = is_stdout_a_tty();
if (out_console) {
hout = GetStdHandle(STD_OUTPUT_HANDLE);
out_code_page = GetConsoleOutputCP();
SetConsoleOutputCP(65001);
if (hout == INVALID_HANDLE_VALUE) {
throw std::runtime_error(
"GetStdHandle(STD_OUTPUT_HANDLE) failed");
}
if (!GetConsoleMode(hout, &dwOriginalOutMode)) {
throw std::runtime_error("GetConsoleMode() failed");
}
DWORD flags = dwOriginalOutMode;
flags |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
flags |= DISABLE_NEWLINE_AUTO_RETURN;
if (!SetConsoleMode(hout, flags)) {
throw std::runtime_error("SetConsoleMode() failed");
}
}

if (keyboard_enabled) {
hin = GetStdHandle(STD_INPUT_HANDLE);
in_code_page = GetConsoleCP();
SetConsoleCP(65001);
if (hin == INVALID_HANDLE_VALUE) {
throw std::runtime_error(
"GetStdHandle(STD_INPUT_HANDLE) failed");
}
if (!GetConsoleMode(hin, &dwOriginalInMode)) {
throw std::runtime_error("GetConsoleMode() failed");
}
DWORD flags = dwOriginalInMode;
flags |= ENABLE_VIRTUAL_TERMINAL_INPUT;
flags &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
if (!SetConsoleMode(hin, flags)) {
throw std::runtime_error("SetConsoleMode() failed");
}
}
#else
BaseTerminal::BaseTerminal(bool enable_keyboard,
bool disable_ctrl_c)
: keyboard_enabled{enable_keyboard} {
// Uncomment this to silently disable raw mode for non-tty
// if (keyboard_enabled) keyboard_enabled = is_stdin_a_tty();
if (keyboard_enabled) {
if (tcgetattr(STDIN_FILENO, &orig_termios) == -1) {
throw std::runtime_error("tcgetattr() failed");
}

// Put terminal in raw mode
struct termios raw = orig_termios;
raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
// This disables output post-processing, requiring explicit \r\n. We
// keep it enabled, so that in C++, one can still just use std::endl
// for EOL instead of "\r\n".
// raw.c_oflag &= ~(OPOST);
raw.c_cflag |= (CS8);
raw.c_lflag &= ~(ECHO | ICANON | IEXTEN);
if (disable_ctrl_c) {
raw.c_lflag &= ~(ISIG);
}
raw.c_cc[VMIN] = 0;
raw.c_cc[VTIME] = 0;

if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1) {
throw std::runtime_error("tcsetattr() failed");
}
}
#endif
}

} // namespace Term
76 changes: 1 addition & 75 deletions cpp-terminal/terminal_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,82 +65,8 @@ class BaseTerminal {
bool keyboard_enabled{};

public:
#ifdef _WIN32
explicit BaseTerminal(bool enable_keyboard = false,
bool /*disable_ctrl_c*/ = true)
: keyboard_enabled{enable_keyboard} {
// Uncomment this to silently disable raw mode for non-tty
// if (keyboard_enabled) keyboard_enabled = is_stdin_a_tty();
out_console = is_stdout_a_tty();
if (out_console) {
hout = GetStdHandle(STD_OUTPUT_HANDLE);
out_code_page = GetConsoleOutputCP();
SetConsoleOutputCP(65001);
if (hout == INVALID_HANDLE_VALUE) {
throw std::runtime_error(
"GetStdHandle(STD_OUTPUT_HANDLE) failed");
}
if (!GetConsoleMode(hout, &dwOriginalOutMode)) {
throw std::runtime_error("GetConsoleMode() failed");
}
DWORD flags = dwOriginalOutMode;
flags |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
flags |= DISABLE_NEWLINE_AUTO_RETURN;
if (!SetConsoleMode(hout, flags)) {
throw std::runtime_error("SetConsoleMode() failed");
}
}

if (keyboard_enabled) {
hin = GetStdHandle(STD_INPUT_HANDLE);
in_code_page = GetConsoleCP();
SetConsoleCP(65001);
if (hin == INVALID_HANDLE_VALUE) {
throw std::runtime_error(
"GetStdHandle(STD_INPUT_HANDLE) failed");
}
if (!GetConsoleMode(hin, &dwOriginalInMode)) {
throw std::runtime_error("GetConsoleMode() failed");
}
DWORD flags = dwOriginalInMode;
flags |= ENABLE_VIRTUAL_TERMINAL_INPUT;
flags &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
if (!SetConsoleMode(hin, flags)) {
throw std::runtime_error("SetConsoleMode() failed");
}
}
#else
explicit BaseTerminal(bool enable_keyboard = false,
bool disable_ctrl_c = true)
: keyboard_enabled{enable_keyboard} {
// Uncomment this to silently disable raw mode for non-tty
// if (keyboard_enabled) keyboard_enabled = is_stdin_a_tty();
if (keyboard_enabled) {
if (tcgetattr(STDIN_FILENO, &orig_termios) == -1) {
throw std::runtime_error("tcgetattr() failed");
}

// Put terminal in raw mode
struct termios raw = orig_termios;
raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
// This disables output post-processing, requiring explicit \r\n. We
// keep it enabled, so that in C++, one can still just use std::endl
// for EOL instead of "\r\n".
// raw.c_oflag &= ~(OPOST);
raw.c_cflag |= (CS8);
raw.c_lflag &= ~(ECHO | ICANON | IEXTEN);
if (disable_ctrl_c) {
raw.c_lflag &= ~(ISIG);
}
raw.c_cc[VMIN] = 0;
raw.c_cc[VTIME] = 0;

if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1) {
throw std::runtime_error("tcsetattr() failed");
}
}
#endif
}
bool disable_ctrl_c = true);

virtual ~BaseTerminal() noexcept(false) {
#ifdef _WIN32
Expand Down
8 changes: 1 addition & 7 deletions cpp-terminalConfig.cmake.in
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
@PACKAGE_INIT@

set_and_check(@PROJECT_NAME@_INCLUDE_DIR "${PACKAGE_PREFIX_DIR}/@CPPTERMINAL_CMAKECONFIG_INCLUDE_DIR@")

check_required_components(@PROJECT_NAME@)

add_library(@PROJECT_NAME@ INTERFACE IMPORTED)
set_property(TARGET @PROJECT_NAME@ PROPERTY INTERFACE_INCLUDE_DIRECTORIES
${@PROJECT_NAME@_INCLUDE_DIR})
include("${CMAKE_INSTALL_PREFIX}/${ConfigPackageLocation}/cpp-terminalTargets.cmake")