예제 #1
0
파일: console.c 프로젝트: 82488059/flinux
static int console_get_poll_status(struct file *f)
{
	/* Writing is always ready */
	struct console_file *console_file = (struct console_file *) f;
	if (console->input_buffer_head != console->input_buffer_tail)
		return LINUX_POLLIN | LINUX_POLLOUT;

	console_lock();
	INPUT_RECORD ir;
	DWORD num_read;
	while (PeekConsoleInputW(console->in, &ir, 1, &num_read) && num_read > 0)
	{
		/* Test if the event will be discarded */
		if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown)
		{
			console_unlock();
			return LINUX_POLLIN | LINUX_POLLOUT;
		}
		else if (ir.EventType == WINDOW_BUFFER_SIZE_EVENT)
			console_retrieve_state();
		/* Discard the event */
		ReadConsoleInputW(console->in, &ir, 1, &num_read);
	}
	/* We don't find any readable events */
	console_unlock();
	return LINUX_POLLOUT;
}
예제 #2
0
파일: console.c 프로젝트: geek-li/flinux
static size_t console_write(struct file *f, const char *buf, size_t count)
{
	struct console_file *console_file = (struct console_file *)f;

	console_lock();
	console_retrieve_state();
	#define OUTPUT() \
		if (last != -1) \
		{ \
			write_normal(buf + last, i - last); \
			last = -1; \
		}
	size_t last = -1;
	size_t i;
	for (i = 0; i < count; i++)
	{
		char ch = buf[i];
		if (ch == 0x1B) /* Escape */
		{
			OUTPUT();
			console->processor = control_escape;
		}
		else if (ch == '\t')
		{
			OUTPUT();
			int x = (console->x + 8) & ~7;
			if (x < console->width)
				set_pos(x, console->y);
			else
				set_pos(console->width - 1, console->y);
		}
		else if (ch == '\b')
		{
			OUTPUT();
			backspace(FALSE);
		}
		else if (ch == '\r')
		{
			OUTPUT();
			if (console->termios.c_oflag & OCRNL)
				nl();
			else
				cr();
		}
		else if (ch == '\n' || ch == '\v' || ch == '\f')
		{
			OUTPUT();
			if (console->termios.c_oflag & ONLCR)
				crnl();
			else
				nl();
		}
		else if (ch == 0x0E || ch == 0x0F)
		{
			/* Shift In and Shift Out */
			OUTPUT();
		}
		else if (console->processor)
			console->processor(ch);
		else if (ch < 0x20)
		{
			OUTPUT();
			log_error("Unhandled control character '\\x%x'\n", ch);
		}
		else if (last == -1)
			last = i;
	}
	OUTPUT();
	/* This will make the caret immediately visible */
	set_pos(console->x, console->y);
	console_unlock();
#if 0
	char str[4096];
	memcpy(str, buf, count);
	str[count] = '\n';
	str[count + 1] = 0;
	log_debug(str);
#endif
	return count;
}
예제 #3
0
파일: console.c 프로젝트: geek-li/flinux
static size_t console_read(struct file *f, char *buf, size_t count)
{
	struct console_file *console_file = (struct console_file *)f;

	console_lock();
	console_retrieve_state();

	size_t bytes_read = 0;
	while (console->input_buffer_head != console->input_buffer_tail && count > 0)
	{
		count--;
		buf[bytes_read++] = console->input_buffer[console->input_buffer_tail];
		console->input_buffer_tail = (console->input_buffer_tail + 1) % MAX_INPUT;
	}
	if (console->termios.c_lflag & ICANON)
	{
		char line[MAX_CANON + 1]; /* One more for storing CR or LF */
		size_t len = 0;
		while (count > 0)
		{
			INPUT_RECORD ir;
			DWORD read;
			ReadConsoleInputA(console->in, &ir, 1, &read);
			if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown)
			{
				switch (ir.Event.KeyEvent.wVirtualKeyCode)
				{
				case VK_RETURN:
				{
					if (!(console->termios.c_iflag & IGNCR))
						line[len++] = console->termios.c_iflag & ICRNL ? '\n' : '\r';
					size_t r = min(count, len);
					memcpy(buf + bytes_read, line, r);
					bytes_read += r;
					count -= r;
					if (r < len)
					{
						/* Some bytes not fit, add to input buffer */
						console_add_input(line + r, len - r);
					}
					if (console->termios.c_lflag & ECHO)
						crnl();
					goto read_done;
				}

				case VK_BACK:
				{
					if (len > 0)
					{
						len--;
						if (console->termios.c_lflag & ECHO)
							backspace(TRUE);
					}
				}
				default:
				{
					char ch = ir.Event.KeyEvent.uChar.AsciiChar;
					if (ch >= 0x20)
					{
						if (len < MAX_CANON)
						{
							line[len++] = ch;
							if (console->termios.c_lflag & ECHO)
								write_normal(&ch, 1);
						}
					}
				}
				}
			}
		}
	}
	else /* Non canonical mode */
	{
		int vtime = console->termios.c_cc[VTIME];
		int vmin = console->termios.c_cc[VMIN];
		while (count > 0)
		{
			if (bytes_read > 0 && bytes_read >= vmin)
				break;
			/* If vmin > 0 and vtime == 0, it is a blocking read, otherwise we need to poll first */
			if (vtime > 0 || (vmin == 0 && vtime == 0))
			{
				if (WaitForSingleObject(console->in, vtime * 100) == WAIT_TIMEOUT)
					break;
			}
			INPUT_RECORD ir;
			DWORD read;
			ReadConsoleInputA(console->in, &ir, 1, &read);
			if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown)
			{
				switch (ir.Event.KeyEvent.wVirtualKeyCode)
				{
				case VK_UP:
					console_buffer_add_string(buf, &bytes_read, &count, console->cursor_key_mode ? "\x1BOA" : "\x1B[A", 3);
					break;

				case VK_DOWN:
					console_buffer_add_string(buf, &bytes_read, &count, console->cursor_key_mode ? "\x1BOB" : "\x1B[B", 3);
					break;

				case VK_RIGHT:
					console_buffer_add_string(buf, &bytes_read, &count, console->cursor_key_mode ? "\x1BOC" : "\x1B[C", 3);
					break;

				case VK_LEFT:
					console_buffer_add_string(buf, &bytes_read, &count, console->cursor_key_mode ? "\x1BOD" : "\x1B[D", 3);
					break;

				case VK_HOME:
					console_buffer_add_string(buf, &bytes_read, &count, console->cursor_key_mode ? "\x1BOH" : "\x1B[H", 3);
					break;

				case VK_END:
					console_buffer_add_string(buf, &bytes_read, &count, console->cursor_key_mode ? "\x1BOF" : "\x1B[F", 3);
					break;

				case VK_INSERT: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[2~", 4); break;
				case VK_DELETE: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[3~", 4); break;
				case VK_PRIOR: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[5~", 4); break;
				case VK_NEXT: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[6~", 4); break;

				case VK_F1: console_buffer_add_string(buf, &bytes_read, &count, "\x1BOP", 3); break;
				case VK_F2: console_buffer_add_string(buf, &bytes_read, &count, "\x1BOQ", 3); break;
				case VK_F3: console_buffer_add_string(buf, &bytes_read, &count, "\x1BOR", 3); break;
				case VK_F4: console_buffer_add_string(buf, &bytes_read, &count, "\x1BOS", 3); break;
				case VK_F5: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[15~", 5); break;
				case VK_F6: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[17~", 5); break;
				case VK_F7: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[18~", 5); break;
				case VK_F8: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[19~", 5); break;
				case VK_F9: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[20~", 5); break;
				case VK_F10: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[21~", 5); break;
				case VK_F11: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[23~", 5); break;
				case VK_F12: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[24~", 5); break;
				case VK_F13: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[25~", 5); break;
				case VK_F14: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[26~", 5); break;
				case VK_F15: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[28~", 5); break;
				case VK_F16: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[29~", 5); break;
				case VK_F17: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[31~", 5); break;
				case VK_F18: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[32~", 5); break;
				case VK_F19: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[33~", 5); break;
				case VK_F20: console_buffer_add_string(buf, &bytes_read, &count, "\x1B[34~", 5); break;

				default:
				{
					char ch = ir.Event.KeyEvent.uChar.AsciiChar;
					if (ch == '\r' && console->termios.c_iflag & IGNCR)
						break;
					if (ch == '\r' && console->termios.c_iflag & ICRNL)
						ch = '\n';
					else if (ch == '\n' && console->termios.c_iflag & ICRNL)
						ch = '\r';
					if (ch > 0)
					{
						count--;
						buf[bytes_read++] = ch;
						if (console->termios.c_lflag & ECHO)
							write_normal(&ch, 1);
					}
				}
				}
			}
			else
			{
				/* TODO: Other types of input */
			}
		}
	}
read_done:
	/* This will make the caret immediately visible */
	set_pos(console->x, console->y);
	console_unlock();
	return bytes_read;
}