| 196 | } |
| 197 | |
| 198 | static char32_t getchar32() { |
| 199 | #if defined(_WIN32) |
| 200 | HANDLE hConsole = GetStdHandle(STD_INPUT_HANDLE); |
| 201 | wchar_t high_surrogate = 0; |
| 202 | |
| 203 | while (true) { |
| 204 | INPUT_RECORD record; |
| 205 | DWORD count; |
| 206 | if (!ReadConsoleInputW(hConsole, &record, 1, &count) || count == 0) { |
| 207 | return WEOF; |
| 208 | } |
| 209 | |
| 210 | if (record.EventType == KEY_EVENT && record.Event.KeyEvent.bKeyDown) { |
| 211 | wchar_t wc = record.Event.KeyEvent.uChar.UnicodeChar; |
| 212 | if (wc == 0) { |
| 213 | const DWORD ctrl_mask = LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED; |
| 214 | const bool ctrl_pressed = (record.Event.KeyEvent.dwControlKeyState & ctrl_mask) != 0; |
| 215 | switch (record.Event.KeyEvent.wVirtualKeyCode) { |
| 216 | case VK_LEFT: return ctrl_pressed ? KEY_CTRL_ARROW_LEFT : KEY_ARROW_LEFT; |
| 217 | case VK_RIGHT: return ctrl_pressed ? KEY_CTRL_ARROW_RIGHT : KEY_ARROW_RIGHT; |
| 218 | case VK_UP: return KEY_ARROW_UP; |
| 219 | case VK_DOWN: return KEY_ARROW_DOWN; |
| 220 | case VK_HOME: return KEY_HOME; |
| 221 | case VK_END: return KEY_END; |
| 222 | case VK_DELETE: return KEY_DELETE; |
| 223 | default: continue; |
| 224 | } |
| 225 | } |
| 226 | |
| 227 | if ((wc >= 0xD800) && (wc <= 0xDBFF)) { // Check if wc is a high surrogate |
| 228 | high_surrogate = wc; |
| 229 | continue; |
| 230 | } |
| 231 | if ((wc >= 0xDC00) && (wc <= 0xDFFF)) { // Check if wc is a low surrogate |
| 232 | if (high_surrogate != 0) { // Check if we have a high surrogate |
| 233 | return ((high_surrogate - 0xD800) << 10) + (wc - 0xDC00) + 0x10000; |
| 234 | } |
| 235 | } |
| 236 | |
| 237 | high_surrogate = 0; // Reset the high surrogate |
| 238 | return static_cast<char32_t>(wc); |
| 239 | } |
| 240 | } |
| 241 | #else |
| 242 | wchar_t wc = getwchar(); |
| 243 | if (static_cast<wint_t>(wc) == WEOF) { |
| 244 | return WEOF; |
| 245 | } |
| 246 | |
| 247 | #if WCHAR_MAX == 0xFFFF |
| 248 | if ((wc >= 0xD800) && (wc <= 0xDBFF)) { // Check if wc is a high surrogate |
| 249 | wchar_t low_surrogate = getwchar(); |
| 250 | if ((low_surrogate >= 0xDC00) && (low_surrogate <= 0xDFFF)) { // Check if the next wchar is a low surrogate |
| 251 | return (static_cast<char32_t>(wc & 0x03FF) << 10) + (low_surrogate & 0x03FF) + 0x10000; |
| 252 | } |
| 253 | } |
| 254 | if ((wc >= 0xD800) && (wc <= 0xDFFF)) { // Invalid surrogate pair |
| 255 | return 0xFFFD; // Return the replacement character U+FFFD |