Mads
Multi-Agent Distributed System
Loading...
Searching...
No Matches
keypress.hpp
Go to the documentation of this file.
1/*
2 _ __
3 | |/ /___ _ _ _ __ _ __ ___ ___ ___
4 | ' // _ \ | | | '_ \| '__/ _ \/ __/ __|
5 | . \ __/ |_| | |_) | | | __/\__ \__ \
6 |_|\_\___|\__, | .__/|_| \___||___/___/
7 |___/|_|
8
9Read a single key press in a portable way.
10*/
11
12#include <iostream>
13#include <string>
14#include <thread> // contains <chrono>
15#include <chrono>
16
17static void kpsleep(const double t) {
18 if (t > 0.0)
19 std::this_thread::sleep_for(std::chrono::milliseconds((int)(1E3 * t + 0.5)));
20}
21
22#if defined(_WIN32)
23#define WIN32_LEAN_AND_MEAN
24#define VC_EXTRALEAN
25#include <Windows.h>
26using namespace std::chrono_literals;
27
28char getch(std::chrono::milliseconds const &ms = 500ms) {
29 HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
30 DWORD dwMilliseconds = ms.count();
31
32 // Save and modify console mode to disable line input
33 DWORD dwMode = 0;
34 GetConsoleMode(hStdin, &dwMode);
35 DWORD newMode = dwMode & ~ENABLE_LINE_INPUT;
36 SetConsoleMode(hStdin, newMode);
37
38 DWORD result = WaitForSingleObject(hStdin, dwMilliseconds);
39
40 char ch = '\0';
41 if (result == WAIT_OBJECT_0) {
42 DWORD dwRead;
43 if (ReadFile(hStdin, &ch, 1, &dwRead, NULL) && dwRead == 1) {
44 // Successfully read character
45 }
46 }
47
48 // Restore original console mode
49 SetConsoleMode(hStdin, dwMode);
50
51 return ch;
52}
53
54#elif defined(__linux__) || defined(__unix__) || defined(__APPLE__)
55#include <sys/ioctl.h>
56#include <termios.h>
57char getch(chrono::milliseconds const &ms = 500ms) {
58 struct timeval tv;
59 Mads::milliseconds_to_tv(ms, tv);
60 struct termios oldt, newt;
61 char ch;
62 fd_set readfds;
63 // struct timeval tv;
64
65 tcgetattr(STDIN_FILENO, &oldt);
66 newt = oldt;
67 newt.c_lflag &= ~(ICANON | ECHO);
68
69 tcsetattr(STDIN_FILENO, TCSANOW, &newt);
70
71 // Set up file descriptor set for stdin
72 FD_ZERO(&readfds);
73 FD_SET(STDIN_FILENO, &readfds);
74
75 int select_result = select(STDIN_FILENO + 1, &readfds, NULL, NULL, &tv);
76
77 if (select_result > 0 && FD_ISSET(STDIN_FILENO, &readfds)) {
78 ch = getchar();
79 } else {
80 ch = '\0'; // timeout or error
81 }
82
83 tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
84
85 return ch;
86}
87#endif // Windows/Linux