aboutsummaryrefslogtreecommitdiff
path: root/win32/termios.c
diff options
context:
space:
mode:
Diffstat (limited to 'win32/termios.c')
-rw-r--r--win32/termios.c128
1 files changed, 128 insertions, 0 deletions
diff --git a/win32/termios.c b/win32/termios.c
new file mode 100644
index 000000000..f18ff7c3b
--- /dev/null
+++ b/win32/termios.c
@@ -0,0 +1,128 @@
1#include "libbb.h"
2
3int tcsetattr(int fd, int mode UNUSED_PARAM, const struct termios *t)
4{
5 if (terminal_mode(FALSE) & VT_INPUT) {
6 HANDLE h = (HANDLE)_get_osfhandle(fd);
7 if (!SetConsoleMode(h, t->imode)) {
8 errno = err_win_to_posix();
9 return -1;
10 }
11 }
12
13 return 0;
14}
15
16int tcgetattr(int fd, struct termios *t)
17{
18 if (terminal_mode(FALSE) & VT_INPUT) {
19 HANDLE h = (HANDLE)_get_osfhandle(fd);
20 if (!GetConsoleMode(h, &t->imode)) {
21 errno = err_win_to_posix();
22 return -1;
23 }
24 }
25 t->c_cc[VINTR] = 3; // ctrl-c
26 t->c_cc[VEOF] = 4; // ctrl-d
27
28 return 0;
29}
30
31int64_t FAST_FUNC windows_read_key(int fd, char *buf UNUSED_PARAM, int timeout)
32{
33 HANDLE cin = GetStdHandle(STD_INPUT_HANDLE);
34 INPUT_RECORD record;
35 DWORD nevent_out, mode;
36 int ret = -1;
37 DWORD alt_pressed = FALSE;
38 DWORD state;
39
40 if (fd != 0)
41 bb_error_msg_and_die("read_key only works on stdin");
42 if (cin == INVALID_HANDLE_VALUE)
43 return -1;
44 GetConsoleMode(cin, &mode);
45 SetConsoleMode(cin, 0);
46
47 while (1) {
48 errno = 0;
49 if (timeout > 0) {
50 if (WaitForSingleObject(cin, timeout) != WAIT_OBJECT_0)
51 goto done;
52 }
53 if (!readConsoleInput_utf8(cin, &record, 1, &nevent_out))
54 goto done;
55
56 if (record.EventType != KEY_EVENT)
57 continue;
58
59 state = record.Event.KeyEvent.dwControlKeyState;
60 if (!record.Event.KeyEvent.bKeyDown) {
61 /* ignore all key up events except Alt */
62 if (!(alt_pressed && (state & LEFT_ALT_PRESSED) == 0 &&
63 record.Event.KeyEvent.wVirtualKeyCode == VK_MENU))
64 continue;
65 }
66 alt_pressed = state & LEFT_ALT_PRESSED;
67
68 if (!record.Event.KeyEvent.uChar.AsciiChar) {
69 if (alt_pressed && !(state & ENHANCED_KEY)) {
70 /* keys on numeric pad used to enter character codes */
71 switch (record.Event.KeyEvent.wVirtualKeyCode) {
72 case VK_NUMPAD0: case VK_INSERT:
73 case VK_NUMPAD1: case VK_END:
74 case VK_NUMPAD2: case VK_DOWN:
75 case VK_NUMPAD3: case VK_NEXT:
76 case VK_NUMPAD4: case VK_LEFT:
77 case VK_NUMPAD5: case VK_CLEAR:
78 case VK_NUMPAD6: case VK_RIGHT:
79 case VK_NUMPAD7: case VK_HOME:
80 case VK_NUMPAD8: case VK_UP:
81 case VK_NUMPAD9: case VK_PRIOR:
82 continue;
83 }
84 }
85
86 switch (record.Event.KeyEvent.wVirtualKeyCode) {
87 case VK_DELETE: ret = KEYCODE_DELETE; break;
88 case VK_INSERT: ret = KEYCODE_INSERT; break;
89 case VK_UP: ret = KEYCODE_UP; break;
90 case VK_DOWN: ret = KEYCODE_DOWN; break;
91 case VK_RIGHT: ret = KEYCODE_RIGHT; break;
92 case VK_LEFT: ret = KEYCODE_LEFT; break;
93 case VK_HOME: ret = KEYCODE_HOME; break;
94 case VK_END: ret = KEYCODE_END; break;
95 case VK_PRIOR: ret = KEYCODE_PAGEUP; break;
96 case VK_NEXT: ret = KEYCODE_PAGEDOWN; break;
97 default:
98 alt_pressed = FALSE;
99 continue;
100 }
101
102 if (state & (RIGHT_ALT_PRESSED|LEFT_ALT_PRESSED))
103 ret &= ~0x20;
104 if (state & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED))
105 ret &= ~0x40;
106 if (state & SHIFT_PRESSED)
107 ret &= ~0x80;
108 goto done;
109 }
110 if ( (record.Event.KeyEvent.uChar.AsciiChar & 0x80) == 0x80 ) {
111 char *s = &record.Event.KeyEvent.uChar.AsciiChar;
112 conToCharBuffA(s, 1);
113 }
114 ret = record.Event.KeyEvent.uChar.AsciiChar;
115 if (state & (RIGHT_ALT_PRESSED|LEFT_ALT_PRESSED)) {
116 switch (ret) {
117 case '\b': ret = KEYCODE_ALT_BACKSPACE; goto done;
118 case 'b': ret = KEYCODE_ALT_LEFT; goto done;
119 case 'd': ret = KEYCODE_ALT_D; goto done;
120 case 'f': ret = KEYCODE_ALT_RIGHT; goto done;
121 }
122 }
123 break;
124 }
125 done:
126 SetConsoleMode(cin, mode);
127 return ret;
128}