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
34 changes: 34 additions & 0 deletions examples/cursor-position-query.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "../tui.hpp"
#include <cassert>
#include <chrono>
#include <cstdint>
// #include <thread>

// returns how much the queries altogether took in ns
uint64_t get_cursor_pos_n(const unsigned n) {
auto start = std::chrono::high_resolution_clock::now();
for (auto i = 0; i < n; ++i) {
// std::cout << "getting cursor position...\n";
auto cursor_pos = tui::cursor::get_position();
// std::cout << "cursor @ {" << cursor_pos.first << ", " << cursor_pos.second << "}\n";
// assert(cursor_pos == cursor_pos_tty);
// std::this_thread::sleep_for(std::chrono::milliseconds(800));
}
auto end = std::chrono::high_resolution_clock::now();
return std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();
}

int main(int argc, char** argv) {
tui::enable_raw_mode();

unsigned n = 8;
if (argc > 1) {
n = std::stoi(argv[1]);
}

auto query_t_sum = get_cursor_pos_n(n);
// std::this_thread::sleep_for(std::chrono::seconds(8));
tui::disable_raw_mode();
std::cout << "getting cursor " << n << " times took: " << query_t_sum / 1000000 << "ms, avg: " << query_t_sum / n <<"ns\n";
return 0;
}
61 changes: 39 additions & 22 deletions tui.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

#ifdef _WIN32 // windows

#include <wchar.h>
#include <windows.h>

#else // not windows
Expand All @@ -20,7 +19,6 @@
#include <cassert>
#include <cstdint>
#include <iostream>
#include <ostream>
#include <sstream>
#include <string>
#include <utility> // for std::pair
Expand Down Expand Up @@ -60,7 +58,7 @@ namespace tui {
exit(1); \
} \
DWORD mode; \
if (!GetConsoleMode(hStdin, &mode)) { \
if (GetConsoleMode(hStdin, &mode) == 0) { \
std::cerr << "error getting the console mode\n"; \
exit(1); \
}
Expand All @@ -73,7 +71,7 @@ namespace tui {
DWORD newMode = mode;
newMode &= ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT);

if (!SetConsoleMode(hStdin, newMode)) {
if (SetConsoleMode(hStdin, newMode) == 0) {
std::cerr << "error setting the console to raw mode\n";
exit(1);
}
Expand Down Expand Up @@ -102,7 +100,7 @@ namespace tui {

// Restore original mode
mode |= (ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT);
if (!SetConsoleMode(hStdin, mode)) {
if (SetConsoleMode(hStdin, mode) == 0) {
std::cerr << "error restoring the console mode\n";
exit(1);
}
Expand All @@ -124,6 +122,27 @@ namespace tui {

#undef win_setup

#ifdef _WIN32
inline CONSOLE_SCREEN_BUFFER_INFO get_console_buf_info() {
HANDLE console = nullptr;
CONSOLE_SCREEN_BUFFER_INFO info;
// create a handle to the console screen
console = CreateFileW(L"CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr,
OPEN_EXISTING, 0, nullptr);
if (console == INVALID_HANDLE_VALUE) {
std::cerr << "couldn't get console handle\n";
exit(1);
}
// calculate the size of the console window
if (GetConsoleScreenBufferInfo(console, &info) == 0) {
std::cerr << "couldn't get console screen buffer info\n";
exit(1);
}
CloseHandle(console);
return info;
}
#endif

namespace cursor {
// template for moving cursor
// moves cursor `n` times to `dir`
Expand Down Expand Up @@ -161,8 +180,17 @@ namespace tui {
// tell the terminal to check where the cursor is
csi_fn(query_position, "6n");

#ifdef _WIN32
// returns: (rows;cols)
inline std::pair<unsigned, unsigned> get_position() {
auto info = get_console_buf_info();
auto rows = info.dwCursorPosition.X + 1;
auto cols = info.dwCursorPosition.Y + 1;
return {rows, cols};
}
#else
// returns: (rows;cols)
// WARN: can be quite slow, don't use on eg. every screen update!
// NOTE: can take a while (eg 16ms) on (relatively) slow terminals
inline std::pair<unsigned, unsigned> get_position() {
query_position();
std::flush(std::cout);
Expand All @@ -179,6 +207,8 @@ namespace tui {

return {rows, cols};
}
#endif

} // namespace cursor

namespace screen {
Expand All @@ -204,22 +234,9 @@ namespace tui {
// returns: (rows;cols)/(y;x)
inline std::pair<unsigned, unsigned> size() {
#ifdef _WIN32
HANDLE console;
CONSOLE_SCREEN_BUFFER_INFO info;
short rows;
short columns;
// create a handle to the console screen
console = CreateFileW(L"CONOUT$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL);
if (console == INVALID_HANDLE_VALUE)
return {0, 0};

// calculate the size of the console window
if (GetConsoleScreenBufferInfo(console, &info) == 0)
return {0, 0};
CloseHandle(console);
columns = info.srWindow.Right - info.srWindow.Left + 1;
rows = info.srWindow.Bottom - info.srWindow.Top + 1;
auto info = get_console_buf_info();
int columns = info.srWindow.Right - info.srWindow.Left + 1;
int rows = info.srWindow.Bottom - info.srWindow.Top + 1;

return {rows, columns};
#else
Expand Down