summaryrefslogtreecommitdiff
path: root/win32/termios.c
blob: 390b90382788494d3ec1629d57755bc9bbd9df92 (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
#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, int timeout)
{
	HANDLE cin = GetStdHandle(STD_INPUT_HANDLE);
	INPUT_RECORD record;
	DWORD nevent_out, mode;
	int ret = -1;

	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'))
				return record.Event.KeyEvent.wVirtualKeyCode & ~0x40;

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