Exemple #1
0
static void screen_scroll_up(struct tsm_screen *con, unsigned int num)
{
	unsigned int i, j, max;
	int ret;

	if (!num)
		return;

	max = con->margin_bottom + 1 - con->margin_top;
	if (num > max)
		num = max;

	/* We cache lines on the stack to speed up the scrolling. However, if
	 * num is too big we might get overflows here so use recursion if num
	 * exceeds a hard-coded limit.
	 * 128 seems to be a sane limit that should never be reached but should
	 * also be small enough so we do not get stack overflows. */
	if (num > 128) {
		screen_scroll_up(con, 128);
		return screen_scroll_up(con, num - 128);
	}
	struct line *cache[num];

	for (i = 0; i < num; ++i) {
		ret = line_new(con, &cache[i], con->size_x);
		if (!ret) {
			link_to_scrollback(con,
					   con->lines[con->margin_top + i]);
		} else {
			cache[i] = con->lines[con->margin_top + i];
			for (j = 0; j < con->size_x; ++j)
				cell_init(con, &cache[i]->cells[j]);
		}
	}

	if (num < max) {
		memmove(&con->lines[con->margin_top],
			&con->lines[con->margin_top + num],
			(max - num) * sizeof(struct line*));
	}

	memcpy(&con->lines[con->margin_top + (max - num)],
	       cache, num * sizeof(struct line*));
}
Exemple #2
0
static void kmscon_buffer_scroll_up(struct kmscon_buffer *buf,
					unsigned int num)
{
	unsigned int i;

	if (!buf || !num)
		return;

	if (num > buf->scroll_y)
		num = buf->scroll_y;

	for (i = 0; i < num; ++i)
		link_to_scrollback(buf, buf->scroll_buf[i]);

	memmove(buf->scroll_buf, &buf->scroll_buf[num],
				(buf->scroll_y - num) * sizeof(struct line*));
	memset(&buf->scroll_buf[buf->scroll_y - num], 0,
						num * sizeof(struct line*));
	buf->scroll_fill = buf->scroll_y;
}
Exemple #3
0
static void screen_scroll_up(struct tsm_screen *con, unsigned int num)
{
	unsigned int i, j, max, pos;
	int ret;

	if (!num)
		return;

	/* TODO: more sophisticated ageing */
	con->age = con->age_cnt;

	max = con->margin_bottom + 1 - con->margin_top;
	if (num > max)
		num = max;

	/* We cache lines on the stack to speed up the scrolling. However, if
	 * num is too big we might get overflows here so use recursion if num
	 * exceeds a hard-coded limit.
	 * 128 seems to be a sane limit that should never be reached but should
	 * also be small enough so we do not get stack overflows. */
	if (num > 128) {
		screen_scroll_up(con, 128);
		return screen_scroll_up(con, num - 128);
	}
	struct line *cache[num];

	for (i = 0; i < num; ++i) {
		pos = con->margin_top + i;
		if (!(con->flags & TSM_SCREEN_ALTERNATE))
			ret = line_new(con, &cache[i], con->size_x);
		else
			ret = -EAGAIN;

		if (!ret) {
			link_to_scrollback(con, con->lines[pos]);
		} else {
			cache[i] = con->lines[pos];
			for (j = 0; j < con->size_x; ++j)
				screen_cell_init(con, &cache[i]->cells[j]);
		}
	}

	if (num < max) {
		memmove(&con->lines[con->margin_top],
			&con->lines[con->margin_top + num],
			(max - num) * sizeof(struct line*));
	}

	memcpy(&con->lines[con->margin_top + (max - num)],
	       cache, num * sizeof(struct line*));

	if (con->sel_active) {
		if (!con->sel_start.line && con->sel_start.y >= 0) {
			con->sel_start.y -= num;
			if (con->sel_start.y < 0) {
				con->sel_start.line = con->sb_last;
				while (con->sel_start.line && ++con->sel_start.y < 0)
					con->sel_start.line = con->sel_start.line->prev;
				con->sel_start.y = SELECTION_TOP;
			}
		}
		if (!con->sel_end.line && con->sel_end.y >= 0) {
			con->sel_end.y -= num;
			if (con->sel_end.y < 0) {
				con->sel_end.line = con->sb_last;
				while (con->sel_end.line && ++con->sel_end.y < 0)
					con->sel_end.line = con->sel_end.line->prev;
				con->sel_end.y = SELECTION_TOP;
			}
		}
	}
}
Exemple #4
0
/* Resize scroll buffer. Despite being used for scroll region only, it is kept
 * big enough to hold both margins too. We do this to allow fast merges of
 * margins and scroll buffer.
 */
static int resize_scrollbuf(struct kmscon_buffer *buf, unsigned int y)
{
	unsigned int fill, i, siz;
	struct line *iter, **cache;

	/* Resize y size by adjusting the scroll-buffer size */
	if (y < buf->scroll_y) {
		/* Shrink scroll-buffer. First move enough elements from the
		 * scroll-buffer into the scroll-back buffer so we can shrink
		 * it without loosing data.
		 * Then reallocate the buffer (we shrink it so we never fail
		 * here) and correctly set values in \buf. If the buffer has
		 * unused lines, we can shrink it down without moving lines
		 * into the scrollback-buffer so first calculate the current
		 * fill of the buffer and then move appropriate amount of
		 * elements to the scrollback buffer.
		 */

		if (buf->scroll_fill > y) {
			for (i = y; i < buf->scroll_fill; ++i)
				link_to_scrollback(buf, buf->scroll_buf[i - y]);

			memmove(buf->scroll_buf,
				&buf->scroll_buf[buf->scroll_fill - y],
				y * sizeof(struct line*));
		}

		siz = buf->mtop_y + buf->mbottom_y + y;
		buf->scroll_buf = realloc(buf->scroll_buf,
						siz * sizeof(struct line*));
		buf->scroll_y = y;
		if (buf->scroll_fill > y)
			buf->scroll_fill = y;
	} else if (y > buf->scroll_y) {
		/* Increase scroll-buffer to new size. Reset all new elements
		 * to NULL so they are empty. Copy existing buffer into new
		 * buffer and correctly set values in \buf.
		 * If we have more space in the buffer, we simply move lines
		 * from the scroll-back buffer into our scroll-buffer if they
		 * are available. Otherwise, we simply add NULL lines.
		 */

		siz = buf->mtop_y + buf->mbottom_y + y;
		cache = malloc(sizeof(struct line*) * siz);
		if (!cache)
			return -ENOMEM;

		memset(cache, 0, sizeof(struct line*) * siz);
		fill = y - buf->scroll_y;

		for (i = 0; i < fill; ++i) {
			iter = get_from_scrollback(buf);
			if (!iter)
				break;

			cache[y - i - 1] = iter;
		}
		buf->scroll_fill += i;
		memmove(cache, &cache[y - i], i * sizeof(struct line*));
		memset(&cache[i + buf->scroll_y], 0,
					(fill - i) * sizeof(struct line*));

		if (buf->scroll_y)
			memcpy(&cache[i], buf->scroll_buf,
					sizeof(struct line*) * buf->scroll_y);

		free(buf->scroll_buf);
		buf->scroll_buf = cache;
		buf->scroll_y = y;
	}

	return 0;
}