Skip to content

Commit ee8ebc1

Browse files
authored
* Add legacy terminal mode detection and supress stupid warnings on Windows
1 parent a40326c commit ee8ebc1

File tree

6 files changed

+102
-70
lines changed

6 files changed

+102
-70
lines changed

cmake/Warnings.cmake

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,12 @@ set(INTEL_WARNINGS_WINDOWS
6262
"/Wall")
6363
#MSVC
6464
set(MSVC_WARNINGS
65-
"/W4"
66-
"/Wall"
67-
"/WL")
65+
"/W4"
66+
"/Wall"
67+
"/WL"
68+
"/wd5045"
69+
"/wd4820"
70+
"/wd4514")
6871

6972
target_compile_options(
7073
${PROJECT_NAME}Warnings

cpp-terminal/color.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@ std::uint8_t Term::Color::to8bits() const
6363
if(getType() == Term::Color::Type::Bit24)
6464
{
6565
// check gray scale in 24 steps
66-
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; }
66+
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); }
6767
// normal color space
68-
return 16 + 36 * (m_bit24[0] / 51) + 6 * (m_bit24[1] / 51) + (m_bit24[2] / 51);
68+
return static_cast<std::uint8_t>(16 + 36 * (m_bit24[0] / 51) + 6 * (m_bit24[1] / 51) + (m_bit24[2] / 51));
6969
}
7070
else
7171
return m_bit8;

cpp-terminal/platforms/terminal.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,10 @@ void Term::Terminal::store_and_restore()
4040
if(!SetConsoleCP(CP_UTF8)) throw Term::Exception("SetConsoleCP(CP_UTF8) failed");
4141

4242
if(!GetConsoleMode(Private::std_cout.getHandler(), &dwOriginalOutMode)) { throw Term::Exception("GetConsoleMode() failed"); }
43-
if(m_terminfo.hasANSIEscapeCode())
44-
{
45-
if(!SetConsoleMode(Private::std_cout.getHandler(), dwOriginalOutMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN)) { throw Term::Exception("SetConsoleMode() failed in destructor"); }
46-
}
4743
if(!GetConsoleMode(Private::std_cin.getHandler(), &dwOriginalInMode)) { throw Term::Exception("GetConsoleMode() failed"); }
48-
if(m_terminfo.hasANSIEscapeCode())
44+
if(!m_terminfo.isLegacy())
4945
{
46+
if(!SetConsoleMode(Private::std_cout.getHandler(), dwOriginalOutMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN)) { throw Term::Exception("SetConsoleMode() failed in destructor"); }
5047
if(!SetConsoleMode(Private::std_cin.getHandler(), dwOriginalInMode | ENABLE_VIRTUAL_TERMINAL_INPUT)) { throw Term::Exception("SetConsoleMode() failed"); }
5148
}
5249
enabled = true;

cpp-terminal/platforms/terminfo.cpp

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,30 @@
11
#ifdef _WIN32
2+
#include "cpp-terminal/platforms/file.hpp"
3+
24
#include <windows.h>
3-
typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
45
#endif
56

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

910
#include <string>
1011

11-
#ifdef _WIN32
12+
#if defined(_WIN32)
1213
bool WindowsVersionGreater(const DWORD& major, const DWORD& minor, const DWORD& patch)
1314
{
14-
RtlGetVersionPtr fn = {reinterpret_cast<RtlGetVersionPtr>(GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "RtlGetVersion"))};
15-
if(fn != nullptr)
15+
#if defined(_MSC_VER)
16+
#pragma warning(push)
17+
#pragma warning(disable : 4191)
18+
#endif
19+
NTSTATUS(WINAPI * getVersion)(PRTL_OSVERSIONINFOW) = (reinterpret_cast<NTSTATUS(WINAPI*)(PRTL_OSVERSIONINFOW)>(GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")), "RtlGetVersion")));
20+
#if defined(_MSC_VER)
21+
#pragma warning(pop)
22+
#endif
23+
if(getVersion != nullptr)
1624
{
1725
RTL_OSVERSIONINFOW rovi;
1826
rovi.dwOSVersionInfoSize = sizeof(rovi);
19-
if(fn(&rovi) == 0)
27+
if(getVersion(&rovi) == 0)
2028
{
2129
if(rovi.dwMajorVersion > major || (rovi.dwMajorVersion == major && (rovi.dwMinorVersion > minor || (rovi.dwMinorVersion == minor && rovi.dwBuildNumber >= patch)))) return true;
2230
else
@@ -27,7 +35,35 @@ bool WindowsVersionGreater(const DWORD& major, const DWORD& minor, const DWORD&
2735
}
2836
#endif
2937

30-
Term::Terminfo::ColorMode Term::Terminfo::m_colorMode{Term::Terminfo::ColorMode::Unset};
38+
void Term::Terminfo::setLegacy()
39+
{
40+
#if defined(_WIN32)
41+
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
42+
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
43+
#endif
44+
if(!hasANSIEscapeCode()) m_legacy = true;
45+
else
46+
{
47+
DWORD dwOriginalOutMode{0};
48+
Term::Private::m_fileInitializer.initialize(); //Just in case
49+
GetConsoleMode(Private::std_cout.getHandler(), &dwOriginalOutMode);
50+
if(!SetConsoleMode(Private::std_cout.getHandler(), dwOriginalOutMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)) m_legacy = true;
51+
else
52+
{
53+
SetConsoleMode(Private::std_cout.getHandler(), dwOriginalOutMode);
54+
m_legacy = false;
55+
}
56+
}
57+
#else
58+
m_legacy = false;
59+
#endif
60+
}
61+
62+
Term::Terminfo::ColorMode Term::Terminfo::getColorMode() { return m_colorMode; }
63+
64+
bool Term::Terminfo::isLegacy() const { return m_legacy; }
65+
66+
Term::Terminfo::ColorMode Term::Terminfo::m_colorMode{ColorMode::Unset};
3167

3268
Term::Terminfo::Terminfo()
3369
{
@@ -37,30 +73,33 @@ Term::Terminfo::Terminfo()
3773
if(Private::getenv("ANSICON").first) m_terminalName = "ansicon";
3874
m_terminalVersion = Private::getenv("TERM_PROGRAM_VERSION").second;
3975
setANSIEscapeCode();
76+
setLegacy();
4077
setColorMode();
4178
}
4279

43-
bool Term::Terminfo::hasANSIEscapeCode() { return m_ANSIEscapeCode; }
80+
bool Term::Terminfo::hasANSIEscapeCode() const { return m_ANSIEscapeCode; }
4481

4582
void Term::Terminfo::setColorMode()
4683
{
47-
std::string colorterm = Private::getenv("COLORTERM").second;
48-
if(colorterm == "truecolor" || colorterm == "24bit") m_colorMode = Term::Terminfo::ColorMode::Bit24;
49-
else
50-
m_colorMode = Term::Terminfo::ColorMode::Bit8;
5184
if(m_terminalName == "Apple_Terminal") m_colorMode = Term::Terminfo::ColorMode::Bit8;
5285
else if(m_terminalName == "JetBrains-JediTerm")
5386
m_colorMode = Term::Terminfo::ColorMode::Bit24;
5487
else if(m_terminalName == "vscode")
5588
m_colorMode = Term::Terminfo::ColorMode::Bit24;
56-
#ifdef _WIN32
57-
else if(WindowsVersionGreater(10, 0, 10586))
58-
m_colorMode = Term::Terminfo::ColorMode::Bit24;
5989
else if(m_terminalName == "ansicon")
6090
m_colorMode = Term::Terminfo::ColorMode::Bit4;
61-
else
91+
else if(m_term == "linux")
92+
m_colorMode = Term::Terminfo::ColorMode::Bit4;
93+
#if defined(_WIN32)
94+
else if(WindowsVersionGreater(10, 0, 10586) && !isLegacy())
95+
m_colorMode = Term::Terminfo::ColorMode::Bit24;
96+
else if(isLegacy())
6297
m_colorMode = Term::Terminfo::ColorMode::Bit4;
6398
#endif
99+
std::string colorterm = Private::getenv("COLORTERM").second;
100+
if((colorterm == "truecolor" || colorterm == "24bit") && m_colorMode != ColorMode::Unset) m_colorMode = Term::Terminfo::ColorMode::Bit24;
101+
else
102+
m_colorMode = Term::Terminfo::ColorMode::Bit4;
64103
}
65104

66105
void Term::Terminfo::setANSIEscapeCode()

cpp-terminal/terminfo.hpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,16 @@ class Terminfo
2525
Bit24,
2626
};
2727
Terminfo();
28-
static ColorMode getColorMode() { return m_colorMode; }
29-
bool hasANSIEscapeCode();
28+
static ColorMode getColorMode();
29+
bool hasANSIEscapeCode() const;
30+
bool isLegacy() const;
3031

3132
private:
3233
void setANSIEscapeCode();
33-
bool m_ANSIEscapeCode{true};
3434
void setColorMode();
35+
void setLegacy();
36+
bool m_ANSIEscapeCode{true};
37+
bool m_legacy{false};
3538
static ColorMode m_colorMode;
3639
std::string m_terminalName;
3740
std::string m_terminalVersion;

examples/CMakeLists.txt

Lines changed: 32 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,32 @@
1-
add_executable(cin cin.cpp)
2-
target_link_libraries(cin PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)
3-
4-
add_executable(minimal minimal.cpp)
5-
target_link_libraries(minimal PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)
6-
7-
add_executable(prompt_multiline prompt_multiline.cpp)
8-
target_link_libraries(prompt_multiline PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)
9-
10-
add_executable(prompt_immediate prompt_immediate.cpp)
11-
target_link_libraries(prompt_immediate PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)
12-
13-
add_executable(prompt_not_immediate prompt_not_immediate.cpp)
14-
target_link_libraries(prompt_not_immediate PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)
15-
16-
add_executable(prompt_simple prompt_simple.cpp)
17-
target_link_libraries(prompt_simple PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)
18-
19-
add_executable(kilo kilo.cpp)
20-
target_link_libraries(kilo PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)
21-
22-
add_executable(menu menu.cpp)
23-
target_link_libraries(menu PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)
24-
25-
add_executable(menu_window menu_window.cpp)
26-
target_link_libraries(menu_window PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)
27-
28-
add_executable(keys keys.cpp)
29-
target_link_libraries(keys PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)
30-
31-
add_executable(colors colors.cpp)
32-
target_link_libraries(colors PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)
33-
34-
add_executable(events events.cpp)
35-
target_link_libraries(events PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)
36-
37-
add_executable(styles styles.cpp)
38-
target_link_libraries(styles PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings)
39-
40-
if(CPPTERMINAL_ENABLE_INSTALL)
41-
install(TARGETS cin minimal prompt_multiline prompt_immediate prompt_not_immediate prompt_simple kilo menu menu_window keys colors RUNTIME DESTINATION bin/examples)
42-
endif()
1+
# Suppress useless warnings in examples but useful in cpp-terminal
2+
add_library(ExamplesWarnings INTERFACE)
3+
target_compile_options(
4+
ExamplesWarnings
5+
INTERFACE
6+
$<$<C_COMPILER_ID:MSVC>:/wd4061>
7+
$<$<CXX_COMPILER_ID:MSVC>:/wd4061>
8+
)
9+
add_library(Warnings::Examples ALIAS ExamplesWarnings)
10+
11+
# Create an example
12+
function(cppterminal_example SOURCE)
13+
add_executable(${SOURCE} ${SOURCE}.cpp)
14+
target_link_libraries(${SOURCE} PRIVATE cpp-terminal::cpp-terminal Warnings::Warnings Warnings::Examples)
15+
if(CPPTERMINAL_ENABLE_INSTALL)
16+
install(TARGETS ${SOURCE} RUNTIME DESTINATION bin/examples)
17+
endif()
18+
endfunction()
19+
20+
cppterminal_example(cin)
21+
cppterminal_example(minimal)
22+
cppterminal_example(prompt_multiline)
23+
cppterminal_example(prompt_immediate)
24+
cppterminal_example(prompt_not_immediate)
25+
cppterminal_example(prompt_simple)
26+
cppterminal_example(kilo)
27+
cppterminal_example(menu)
28+
cppterminal_example(menu_window)
29+
cppterminal_example(keys)
30+
cppterminal_example(colors)
31+
cppterminal_example(events)
32+
cppterminal_example(styles)

0 commit comments

Comments
 (0)