Skip to content

Commit be2a27a

Browse files
authored
Merge pull request #178 from flagarde/master
Add has_ansi_escape_code()
2 parents 6df1703 + b6a5a77 commit be2a27a

File tree

3 files changed

+53
-13
lines changed

3 files changed

+53
-13
lines changed

cpp-terminal/private/platform.cpp

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,24 @@
44
#include <conio.h>
55
#include <io.h>
66
#include <windows.h>
7-
#else
8-
#include <sys/ioctl.h>
9-
#include <termios.h>
10-
#include <unistd.h>
11-
#include <cerrno>
12-
#endif
13-
14-
#include <stdexcept>
15-
7+
typedef NTSTATUS(WINAPI* RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
168
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
179
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
1810
#endif
19-
2011
#ifndef DISABLE_NEWLINE_AUTO_RETURN
2112
#define DISABLE_NEWLINE_AUTO_RETURN 0x0008
2213
#endif
23-
2414
#ifndef ENABLE_VIRTUAL_TERMINAL_INPUT
2515
#define ENABLE_VIRTUAL_TERMINAL_INPUT 0x0200
2616
#endif
17+
#else
18+
#include <sys/ioctl.h>
19+
#include <termios.h>
20+
#include <unistd.h>
21+
#include <cerrno>
22+
#endif
23+
24+
#include <stdexcept>
2725

2826
bool Term::Private::is_stdin_a_tty() {
2927
#ifdef _WIN32
@@ -116,6 +114,40 @@ bool Term::Private::read_raw(char* s) {
116114
#endif
117115
}
118116

117+
bool Term::Private::has_ansi_escape_code() {
118+
#ifdef _WIN32
119+
static bool checked{false};
120+
static bool has_ansi{false};
121+
if (checked == false) {
122+
const DWORD MINV_MAJOR{10};
123+
const DWORD MINV_MINOR{0};
124+
const DWORD MINV_BUILD{10586};
125+
HMODULE hMod{GetModuleHandle(TEXT("ntdll.dll"))};
126+
if (hMod) {
127+
RtlGetVersionPtr fn = {reinterpret_cast<RtlGetVersionPtr>(
128+
GetProcAddress(hMod, "RtlGetVersion"))};
129+
if (fn != nullptr) {
130+
RTL_OSVERSIONINFOW rovi{0};
131+
rovi.dwOSVersionInfoSize = sizeof(rovi);
132+
if (fn(&rovi) == 0) {
133+
if (rovi.dwMajorVersion > MINV_MAJOR ||
134+
(rovi.dwMajorVersion == MINV_MAJOR &&
135+
(rovi.dwMinorVersion > MINV_MINOR ||
136+
(rovi.dwMinorVersion == MINV_MINOR &&
137+
rovi.dwBuildNumber >= MINV_BUILD)))) {
138+
has_ansi = true;
139+
}
140+
}
141+
}
142+
}
143+
checked = true;
144+
}
145+
return has_ansi;
146+
#else
147+
return true;
148+
#endif
149+
}
150+
119151
Term::Private::BaseTerminal::~BaseTerminal() noexcept(false) {
120152
#ifdef _WIN32
121153
if (out_console) {
@@ -161,7 +193,9 @@ Term::Private::BaseTerminal::BaseTerminal(bool enable_keyboard,
161193
throw std::runtime_error("GetConsoleMode() failed");
162194
}
163195
DWORD flags = dwOriginalOutMode;
164-
flags |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
196+
if (has_ansi_escape_code()) {
197+
flags |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
198+
}
165199
flags |= DISABLE_NEWLINE_AUTO_RETURN;
166200
if (!SetConsoleMode(hout, flags)) {
167201
throw std::runtime_error("SetConsoleMode() failed");
@@ -179,7 +213,9 @@ Term::Private::BaseTerminal::BaseTerminal(bool enable_keyboard,
179213
throw std::runtime_error("GetConsoleMode() failed");
180214
}
181215
DWORD flags = dwOriginalInMode;
182-
flags |= ENABLE_VIRTUAL_TERMINAL_INPUT;
216+
if (has_ansi_escape_code()) {
217+
flags |= ENABLE_VIRTUAL_TERMINAL_INPUT;
218+
}
183219
flags &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT);
184220
if (!SetConsoleMode(hin, flags)) {
185221
throw std::runtime_error("SetConsoleMode() failed");

cpp-terminal/private/platform.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ bool get_term_size(int& rows, int& cols);
3636
// This can't be made inline
3737
bool read_raw(char* s);
3838

39+
bool has_ansi_escape_code();
40+
3941
/* Note: the code that uses Terminal must be inside try/catch block, otherwise
4042
* the destructors will not be called when an exception happens and the
4143
* terminal will not be left in a good state. Terminal uses exceptions when

examples/colors.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ int main() {
5858
<< "\033[0m";
5959
}
6060
std::cout << "\n";
61+
std::cout << "Press any key to quit" << std::endl;
62+
std::cin.get();
6163

6264
} catch (const std::runtime_error& re) {
6365
std::cerr << "Runtime error: " << re.what() << std::endl;

0 commit comments

Comments
 (0)