Exemplo n.º 1
0
static int read_up_to(int n) {
	assert(n > 0);
	const int prevlen = input_buffer.len;
	bytebuffer_resize(&input_buffer, prevlen + n);

	int read_n = 0;
	while (read_n <= n) {
		ssize_t r = 0;
		if (read_n < n) {
			r = read(inout, input_buffer.buf + prevlen + read_n, n - read_n);
		}
#ifdef __CYGWIN__
		// While linux man for tty says when VMIN == 0 && VTIME == 0, read
		// should return 0 when there is nothing to read, cygwin's read returns
		// -1. Not sure why and if it's correct to ignore it, but let's pretend
		// it's zero.
		if (r < 0) r = 0;
#endif
		if (r < 0) {
			// EAGAIN / EWOULDBLOCK shouldn't occur here
			assert(errno != EAGAIN && errno != EWOULDBLOCK);
			return -1;
		} else if (r > 0) {
			read_n += r;
		} else {
			bytebuffer_resize(&input_buffer, prevlen + read_n);
			return read_n;
		}
	}
	assert(!"unreachable");
	return 0;
}
Exemplo n.º 2
0
static int wait_fill_event(struct tb_event *event, struct timeval *timeout)
{
	// ;-)
#define ENOUGH_DATA_FOR_PARSING 64
	fd_set events;
	memset(event, 0, sizeof(struct tb_event));

	// try to extract event from input buffer, return on success
	event->type = TB_EVENT_KEY;
	if (extract_event(event, &input_buffer, inputmode))
		return TB_EVENT_KEY;

	// it looks like input buffer is incomplete, let's try the short path,
	// but first make sure there is enough space
	int prevlen = input_buffer.len;
	bytebuffer_resize(&input_buffer, prevlen + ENOUGH_DATA_FOR_PARSING);
	ssize_t r = read(inout,	input_buffer.buf + prevlen,
		ENOUGH_DATA_FOR_PARSING);
	if (r < 0) {
		// EAGAIN / EWOULDBLOCK shouldn't occur here
		assert(errno != EAGAIN && errno != EWOULDBLOCK);
		return -1;
	} else if (r > 0) {
		bytebuffer_resize(&input_buffer, prevlen + r);
		if (extract_event(event, &input_buffer, inputmode))
			return TB_EVENT_KEY;
	} else {
		bytebuffer_resize(&input_buffer, prevlen);
	}

	// r == 0, or not enough data, let's go to select
	while (1) {
		FD_ZERO(&events);
		FD_SET(inout, &events);
		FD_SET(winch_fds[0], &events);
		int maxfd = (winch_fds[0] > inout) ? winch_fds[0] : inout;
		int result = select(maxfd+1, &events, 0, 0, timeout);
		if (!result)
			return 0;

		if (FD_ISSET(inout, &events)) {
			event->type = TB_EVENT_KEY;
			prevlen = input_buffer.len;
			bytebuffer_resize(&input_buffer,
				prevlen + ENOUGH_DATA_FOR_PARSING);
			r = read(inout, input_buffer.buf + prevlen,
				ENOUGH_DATA_FOR_PARSING);
			if (r < 0) {
				// EAGAIN / EWOULDBLOCK shouldn't occur here
				assert(errno != EAGAIN && errno != EWOULDBLOCK);
				return -1;
			}
			assert(r > 0);
			bytebuffer_resize(&input_buffer, prevlen + r);
			if (extract_event(event, &input_buffer, inputmode))
				return TB_EVENT_KEY;
		}
		if (FD_ISSET(winch_fds[0], &events)) {
			event->type = TB_EVENT_RESIZE;
			int zzz = 0;
			read(winch_fds[0], &zzz, sizeof(int));
			buffer_size_change_request = 1;
			get_term_size(&event->w, &event->h);
			return TB_EVENT_RESIZE;
		}
	}
}