aboutsummaryrefslogtreecommitdiff
path: root/win32/termios.c
blob: 658af4a26d5c56f9ef8accdcf4ef2f3b448beabf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include "libbb.h"

int tcsetattr(int fd UNUSED_PARAM, int mode UNUSED_PARAM,  const struct termios *t UNUSED_PARAM)
{
	return -1;
}

int tcgetattr(int fd UNUSED_PARAM, struct termios *t UNUSED_PARAM)
{
	return -1;
}

int64_t FAST_FUNC read_key(int fd, char *buf UNUSED_PARAM, int timeout)
{
	HANDLE cin = GetStdHandle(STD_INPUT_HANDLE);
	INPUT_RECORD record;
	DWORD nevent_out, mode;
	int ret = -1;
	char *s;

	if (fd != 0)
		bb_error_msg_and_die("read_key only works on stdin");
	if (cin == INVALID_HANDLE_VALUE)
		return -1;
	GetConsoleMode(cin, &mode);
	SetConsoleMode(cin, 0);

	if (timeout > 0) {
		if (WaitForSingleObject(cin, timeout) != WAIT_OBJECT_0)
			goto done;
	}
	while (1) {
		if (!ReadConsoleInput(cin, &record, 1, &nevent_out))
			goto done;
		if (record.EventType != KEY_EVENT || !record.Event.KeyEvent.bKeyDown)
			continue;
		if (!record.Event.KeyEvent.uChar.AsciiChar) {
			DWORD state = record.Event.KeyEvent.dwControlKeyState;

			if (state & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED) &&
			    (record.Event.KeyEvent.wVirtualKeyCode >= 'A' &&
			     record.Event.KeyEvent.wVirtualKeyCode <= 'Z')) {
				ret = record.Event.KeyEvent.wVirtualKeyCode & ~0x40;
				break;
			}

			switch (record.Event.KeyEvent.wVirtualKeyCode) {
			case VK_DELETE: ret = KEYCODE_DELETE; goto done;
			case VK_INSERT: ret = KEYCODE_INSERT; goto done;
			case VK_UP: ret = KEYCODE_UP; goto done;
			case VK_DOWN: ret = KEYCODE_DOWN; goto done;
			case VK_RIGHT:
				if (state & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED)) {
					ret = KEYCODE_CTRL_RIGHT;
					goto done;
				}
				ret = KEYCODE_RIGHT;
				goto done;
			case VK_LEFT:
				if (state & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED)) {
					ret = KEYCODE_CTRL_LEFT;
					goto done;
				}
				ret = KEYCODE_LEFT;
				goto done;
			case VK_HOME: ret = KEYCODE_HOME; goto done;
			case VK_END: ret = KEYCODE_END; goto done;
			case VK_PRIOR: ret = KEYCODE_PAGEUP; goto done;
			case VK_NEXT: ret = KEYCODE_PAGEDOWN; goto done;
			}
			continue;
		}
		if ( (record.Event.KeyEvent.uChar.AsciiChar & 0x80) == 0x80 ) {
			s = &record.Event.KeyEvent.uChar.AsciiChar;
			OemToCharBuff(s, s, 1);
		}
		ret = record.Event.KeyEvent.uChar.AsciiChar;
		break;
	}
 done:
	SetConsoleMode(cin, mode);
	return ret;
}