diff options
Diffstat (limited to 'win32/termios.c')
-rw-r--r-- | win32/termios.c | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/win32/termios.c b/win32/termios.c new file mode 100644 index 000000000..658af4a26 --- /dev/null +++ b/win32/termios.c | |||
@@ -0,0 +1,83 @@ | |||
1 | #include "libbb.h" | ||
2 | |||
3 | int tcsetattr(int fd UNUSED_PARAM, int mode UNUSED_PARAM, const struct termios *t UNUSED_PARAM) | ||
4 | { | ||
5 | return -1; | ||
6 | } | ||
7 | |||
8 | int tcgetattr(int fd UNUSED_PARAM, struct termios *t UNUSED_PARAM) | ||
9 | { | ||
10 | return -1; | ||
11 | } | ||
12 | |||
13 | int64_t FAST_FUNC read_key(int fd, char *buf UNUSED_PARAM, int timeout) | ||
14 | { | ||
15 | HANDLE cin = GetStdHandle(STD_INPUT_HANDLE); | ||
16 | INPUT_RECORD record; | ||
17 | DWORD nevent_out, mode; | ||
18 | int ret = -1; | ||
19 | char *s; | ||
20 | |||
21 | if (fd != 0) | ||
22 | bb_error_msg_and_die("read_key only works on stdin"); | ||
23 | if (cin == INVALID_HANDLE_VALUE) | ||
24 | return -1; | ||
25 | GetConsoleMode(cin, &mode); | ||
26 | SetConsoleMode(cin, 0); | ||
27 | |||
28 | if (timeout > 0) { | ||
29 | if (WaitForSingleObject(cin, timeout) != WAIT_OBJECT_0) | ||
30 | goto done; | ||
31 | } | ||
32 | while (1) { | ||
33 | if (!ReadConsoleInput(cin, &record, 1, &nevent_out)) | ||
34 | goto done; | ||
35 | if (record.EventType != KEY_EVENT || !record.Event.KeyEvent.bKeyDown) | ||
36 | continue; | ||
37 | if (!record.Event.KeyEvent.uChar.AsciiChar) { | ||
38 | DWORD state = record.Event.KeyEvent.dwControlKeyState; | ||
39 | |||
40 | if (state & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED) && | ||
41 | (record.Event.KeyEvent.wVirtualKeyCode >= 'A' && | ||
42 | record.Event.KeyEvent.wVirtualKeyCode <= 'Z')) { | ||
43 | ret = record.Event.KeyEvent.wVirtualKeyCode & ~0x40; | ||
44 | break; | ||
45 | } | ||
46 | |||
47 | switch (record.Event.KeyEvent.wVirtualKeyCode) { | ||
48 | case VK_DELETE: ret = KEYCODE_DELETE; goto done; | ||
49 | case VK_INSERT: ret = KEYCODE_INSERT; goto done; | ||
50 | case VK_UP: ret = KEYCODE_UP; goto done; | ||
51 | case VK_DOWN: ret = KEYCODE_DOWN; goto done; | ||
52 | case VK_RIGHT: | ||
53 | if (state & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED)) { | ||
54 | ret = KEYCODE_CTRL_RIGHT; | ||
55 | goto done; | ||
56 | } | ||
57 | ret = KEYCODE_RIGHT; | ||
58 | goto done; | ||
59 | case VK_LEFT: | ||
60 | if (state & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED)) { | ||
61 | ret = KEYCODE_CTRL_LEFT; | ||
62 | goto done; | ||
63 | } | ||
64 | ret = KEYCODE_LEFT; | ||
65 | goto done; | ||
66 | case VK_HOME: ret = KEYCODE_HOME; goto done; | ||
67 | case VK_END: ret = KEYCODE_END; goto done; | ||
68 | case VK_PRIOR: ret = KEYCODE_PAGEUP; goto done; | ||
69 | case VK_NEXT: ret = KEYCODE_PAGEDOWN; goto done; | ||
70 | } | ||
71 | continue; | ||
72 | } | ||
73 | if ( (record.Event.KeyEvent.uChar.AsciiChar & 0x80) == 0x80 ) { | ||
74 | s = &record.Event.KeyEvent.uChar.AsciiChar; | ||
75 | OemToCharBuff(s, s, 1); | ||
76 | } | ||
77 | ret = record.Event.KeyEvent.uChar.AsciiChar; | ||
78 | break; | ||
79 | } | ||
80 | done: | ||
81 | SetConsoleMode(cin, mode); | ||
82 | return ret; | ||
83 | } | ||