aboutsummaryrefslogtreecommitdiff
path: root/win32/termios.c
blob: 108a746efeffb883b769ae77aa50b7b8e8673cf1 (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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include "libbb.h"

static struct termios dummy = {
	0,		/* c_iflag */
	0,		/* c_oflag */
	0,		/* c_cflag */
	0,		/* c_lflag */
	'\0',	/* c_line */
	"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",	/* c_cc[NCCS] */
	B9600,	/* c_ispeed */
	B9600	/* c_ospeed */
};

int tcsetattr(int fd UNUSED_PARAM, int mode UNUSED_PARAM,  const struct termios *t)
{
	dummy = *t;
	return 0;
}

int tcgetattr(int fd UNUSED_PARAM, struct termios *t)
{
	*t = dummy;
	return 0;
}

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;
}

speed_t cfgetispeed(const struct termios *termios_p)
{
	return termios_p->c_ispeed;
}

speed_t cfgetospeed(const struct termios *termios_p)
{
	return termios_p->c_ospeed;
}

int cfsetispeed(struct termios *termios_p, speed_t speed)
{
	termios_p->c_ispeed = speed;
	return 0;
}

int cfsetospeed(struct termios *termios_p, speed_t speed)
{
	termios_p->c_ospeed = speed;
	return 0;
}