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