Skip to content
9 changes: 6 additions & 3 deletions cmake/Warnings.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,12 @@ set(INTEL_WARNINGS_WINDOWS
"/Wall")
#MSVC
set(MSVC_WARNINGS
"/W4"
"/Wall"
"/WL")
"/W4"
"/Wall"
"/WL"
"/wd5045"
"/wd4820"
"/wd4514")

target_compile_options(
${PROJECT_NAME}Warnings
Expand Down
4 changes: 2 additions & 2 deletions cpp-terminal/color.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ std::uint8_t Term::Color::to8bits() const
if(getType() == Term::Color::Type::Bit24)
{
// check gray scale in 24 steps
if(m_bit24[0] == m_bit24[1] && m_bit24[0] == m_bit24[2]) { return 232 + m_bit24[0] / 32 + m_bit24[1] / 32 + m_bit24[2] / 32; }
if(m_bit24[0] == m_bit24[1] && m_bit24[0] == m_bit24[2]) { return static_cast<std::uint8_t>(232 + m_bit24[0] / 32 + m_bit24[1] / 32 + m_bit24[2] / 32); }
// normal color space
return 16 + 36 * (m_bit24[0] / 51) + 6 * (m_bit24[1] / 51) + (m_bit24[2] / 51);
return static_cast<std::uint8_t>(16 + 36 * (m_bit24[0] / 51) + 6 * (m_bit24[1] / 51) + (m_bit24[2] / 51));
}
else
return m_bit8;
Expand Down
7 changes: 2 additions & 5 deletions cpp-terminal/platforms/terminal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,10 @@ void Term::Terminal::store_and_restore()
if(!SetConsoleCP(CP_UTF8)) throw Term::Exception("SetConsoleCP(CP_UTF8) failed");

if(!GetConsoleMode(Private::std_cout.getHandler(), &dwOriginalOutMode)) { throw Term::Exception("GetConsoleMode() failed"); }
if(m_terminfo.hasANSIEscapeCode())
{
if(!SetConsoleMode(Private::std_cout.getHandler(), dwOriginalOutMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN)) { throw Term::Exception("SetConsoleMode() failed in destructor"); }
}
if(!GetConsoleMode(Private::std_cin.getHandler(), &dwOriginalInMode)) { throw Term::Exception("GetConsoleMode() failed"); }
if(m_terminfo.hasANSIEscapeCode())
if(!m_terminfo.isLegacy())
{
if(!SetConsoleMode(Private::std_cout.getHandler(), dwOriginalOutMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN)) { throw Term::Exception("SetConsoleMode() failed in destructor"); }
if(!SetConsoleMode(Private::std_cin.getHandler(), dwOriginalInMode | ENABLE_VIRTUAL_TERMINAL_INPUT)) { throw Term::Exception("SetConsoleMode() failed"); }
}
enabled = true;
Expand Down
69 changes: 54 additions & 15 deletions cpp-terminal/platforms/terminfo.cpp
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
#ifdef _WIN32
#include "cpp-terminal/platforms/file.hpp"

#include <windows.h>
typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
#endif

#include "cpp-terminal/platforms/env.hpp"
#include "cpp-terminal/terminfo.hpp"

#include <string>

#ifdef _WIN32
#if defined(_WIN32)
bool WindowsVersionGreater(const DWORD& major, const DWORD& minor, const DWORD& patch)
{
RtlGetVersionPtr fn = {reinterpret_cast<RtlGetVersionPtr>(GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "RtlGetVersion"))};
if(fn != nullptr)
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4191)
#endif
NTSTATUS(WINAPI * getVersion)(PRTL_OSVERSIONINFOW) = (reinterpret_cast<NTSTATUS(WINAPI*)(PRTL_OSVERSIONINFOW)>(GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "RtlGetVersion")));
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
if(getVersion != nullptr)
{
RTL_OSVERSIONINFOW rovi;
rovi.dwOSVersionInfoSize = sizeof(rovi);
if(fn(&rovi) == 0)
if(getVersion(&rovi) == 0)
{
if(rovi.dwMajorVersion > major || (rovi.dwMajorVersion == major && (rovi.dwMinorVersion > minor || (rovi.dwMinorVersion == minor && rovi.dwBuildNumber >= patch)))) return true;
else
Expand All @@ -27,7 +35,35 @@ bool WindowsVersionGreater(const DWORD& major, const DWORD& minor, const DWORD&
}
#endif

Term::Terminfo::ColorMode Term::Terminfo::m_colorMode{Term::Terminfo::ColorMode::Unset};
void Term::Terminfo::setLegacy()
{
#if defined(_WIN32)
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
#endif
if(!hasANSIEscapeCode()) m_legacy = true;
else
{
DWORD dwOriginalOutMode{0};
Term::Private::m_fileInitializer.initialize(); //Just in case
GetConsoleMode(Private::std_cout.getHandler(), &dwOriginalOutMode);
if(!SetConsoleMode(Private::std_cout.getHandler(), dwOriginalOutMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) m_legacy = true;
else
{
SetConsoleMode(Private::std_cout.getHandler(), dwOriginalOutMode);
m_legacy = false;
}
}
#else
m_legacy = false;
#endif
}

Term::Terminfo::ColorMode Term::Terminfo::getColorMode() { return m_colorMode; }

bool Term::Terminfo::isLegacy() const { return m_legacy; }

Term::Terminfo::ColorMode Term::Terminfo::m_colorMode{ColorMode::Unset};

Term::Terminfo::Terminfo()
{
Expand All @@ -37,30 +73,33 @@ Term::Terminfo::Terminfo()
if(Private::getenv("ANSICON").first) m_terminalName = "ansicon";
m_terminalVersion = Private::getenv("TERM_PROGRAM_VERSION").second;
setANSIEscapeCode();
setLegacy();
setColorMode();
}

bool Term::Terminfo::hasANSIEscapeCode() { return m_ANSIEscapeCode; }
bool Term::Terminfo::hasANSIEscapeCode() const { return m_ANSIEscapeCode; }

void Term::Terminfo::setColorMode()
{
std::string colorterm = Private::getenv("COLORTERM").second;
if(colorterm == "truecolor" || colorterm == "24bit") m_colorMode = Term::Terminfo::ColorMode::Bit24;
else
m_colorMode = Term::Terminfo::ColorMode::Bit8;
if(m_terminalName == "Apple_Terminal") m_colorMode = Term::Terminfo::ColorMode::Bit8;
else if(m_terminalName == "JetBrains-JediTerm")
m_colorMode = Term::Terminfo::ColorMode::Bit24;
else if(m_terminalName == "vscode")
m_colorMode = Term::Terminfo::ColorMode::Bit24;
#ifdef _WIN32
else if(WindowsVersionGreater(10, 0, 10586))
m_colorMode = Term::Terminfo::ColorMode::Bit24;
else if(m_terminalName == "ansicon")
m_colorMode = Term::Terminfo::ColorMode::Bit4;
else
else if(m_term == "linux")
m_colorMode = Term::Terminfo::ColorMode::Bit4;
#if defined(_WIN32)
else if(WindowsVersionGreater(10, 0, 10586) && !isLegacy())
m_colorMode = Term::Terminfo::ColorMode::Bit24;
else if(isLegacy())
m_colorMode = Term::Terminfo::ColorMode::Bit4;
#endif
std::string colorterm = Private::getenv("COLORTERM").second;
if((colorterm == "truecolor" || colorterm == "24bit") && m_colorMode != ColorMode::Unset) m_colorMode = Term::Terminfo::ColorMode::Bit24;
else
m_colorMode = Term::Terminfo::ColorMode::Bit4;
}

void Term::Terminfo::setANSIEscapeCode()
Expand Down
9 changes: 6 additions & 3 deletions cpp-terminal/terminfo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,16 @@ class Terminfo
Bit24,
};
Terminfo();
static ColorMode getColorMode() { return m_colorMode; }
bool hasANSIEscapeCode();
static ColorMode getColorMode();
bool hasANSIEscapeCode() const;
bool isLegacy() const;

private:
void setANSIEscapeCode();
bool m_ANSIEscapeCode{true};
void setColorMode();
void setLegacy();
bool m_ANSIEscapeCode{true};
bool m_legacy{false};
static ColorMode m_colorMode;
std::string m_terminalName;
std::string m_terminalVersion;
Expand Down
74 changes: 32 additions & 42 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,42 +1,32 @@
add_executable(cin cin.cpp)
target_link_libraries(cin PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)

add_executable(minimal minimal.cpp)
target_link_libraries(minimal PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)

add_executable(prompt_multiline prompt_multiline.cpp)
target_link_libraries(prompt_multiline PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)

add_executable(prompt_immediate prompt_immediate.cpp)
target_link_libraries(prompt_immediate PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)

add_executable(prompt_not_immediate prompt_not_immediate.cpp)
target_link_libraries(prompt_not_immediate PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)

add_executable(prompt_simple prompt_simple.cpp)
target_link_libraries(prompt_simple PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)

add_executable(kilo kilo.cpp)
target_link_libraries(kilo PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)

add_executable(menu menu.cpp)
target_link_libraries(menu PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)

add_executable(menu_window menu_window.cpp)
target_link_libraries(menu_window PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)

add_executable(keys keys.cpp)
target_link_libraries(keys PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)

add_executable(colors colors.cpp)
target_link_libraries(colors PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)

add_executable(events events.cpp)
target_link_libraries(events PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)

add_executable(styles styles.cpp)
target_link_libraries(styles PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)

if(CPPTERMINAL_ENABLE_INSTALL)
install(TARGETS cin minimal prompt_multiline prompt_immediate prompt_not_immediate prompt_simple kilo menu menu_window keys colors RUNTIME DESTINATION bin/examples)
endif()
# Suppress useless warnings in examples but useful in cpp-terminal
add_library(ExamplesWarnings INTERFACE)
target_compile_options(
ExamplesWarnings
INTERFACE
$<$<C_COMPILER_ID:MSVC>:/wd4061>
$<$<CXX_COMPILER_ID:MSVC>:/wd4061>
)
add_library(Warnings::Examples ALIAS ExamplesWarnings)

# Create an example
function(cppterminal_example SOURCE)
add_executable(${SOURCE} ${SOURCE}.cpp)
target_link_libraries(${SOURCE} PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings Warnings::Examples)
if(CPPTERMINAL_ENABLE_INSTALL)
install(TARGETS ${SOURCE} RUNTIME DESTINATION bin/examples)
endif()
endfunction()

cppterminal_example(cin)
cppterminal_example(minimal)
cppterminal_example(prompt_multiline)
cppterminal_example(prompt_immediate)
cppterminal_example(prompt_not_immediate)
cppterminal_example(prompt_simple)
cppterminal_example(kilo)
cppterminal_example(menu)
cppterminal_example(menu_window)
cppterminal_example(keys)
cppterminal_example(colors)
cppterminal_example(events)
cppterminal_example(styles)