Ejemplo n.º 1
0
Archivo: grid.c Proyecto: ershov/tmux
/* Join line data. */
void
grid_reflow_join(struct grid *dst, u_int *py, struct grid_line *src_gl,
    u_int new_x)
{
	struct grid_line	*dst_gl = &dst->linedata[(*py) - 1];
	u_int			 left, to_copy, ox, nx;

	/* How much is left on the old line? */
	left = new_x - dst_gl->cellsize;

	/* Work out how much to append. */
	to_copy = src_gl->cellsize;
	if (to_copy > left)
		to_copy = left;
	ox = dst_gl->cellsize;
	nx = ox + to_copy;

	/* Resize the destination line. */
	dst_gl->celldata = xreallocarray(dst_gl->celldata, nx,
	    sizeof *dst_gl->celldata);
	dst_gl->cellsize = nx;

	/* Append as much as possible. */
	grid_reflow_copy(dst_gl, ox, src_gl, 0, to_copy);

	/* If there is any left in the source, split it. */
	if (src_gl->cellsize > to_copy) {
		dst_gl->flags |= GRID_LINE_WRAPPED;

		src_gl->cellsize -= to_copy;
		grid_reflow_split(dst, py, src_gl, new_x, to_copy);
	}
}
Ejemplo n.º 2
0
/*
 * Reflow lines from src grid into dst grid of width new_x. Returns number of
 * lines fewer in the visible area. The source grid is destroyed.
 */
u_int
grid_reflow(struct grid *dst, struct grid *src, u_int new_x)
{
	u_int			 py, sy, line;
	int			 previous_wrapped;
	struct grid_line	*src_gl;

	py = 0;
	sy = src->sy;

	previous_wrapped = 0;
	for (line = 0; line < sy + src->hsize; line++) {
		src_gl = src->linedata + line;
		if (!previous_wrapped) {
			/* Wasn't wrapped. If smaller, move to destination. */
			if (src_gl->cellsize <= new_x)
				grid_reflow_move(dst, &py, src_gl);
			else
				grid_reflow_split(dst, &py, src_gl, new_x, 0);
		} else {
			/* Previous was wrapped. Try to join. */
			grid_reflow_join(dst, &py, src_gl, new_x);
		}
		previous_wrapped = src_gl->flags & GRID_LINE_WRAPPED;
	}

	grid_destroy(src);

	if (py > sy)
		return (0);
	return (sy - py);
}
Ejemplo n.º 3
0
/* Reflow lines on grid to new width. */
void
grid_reflow(struct grid *gd, u_int sx)
{
	struct grid		*target;
	struct grid_line	*gl;
	struct grid_cell	 gc;
	u_int			 yy, width, i, at, first;

	/*
	 * Create a destination grid. This is just used as a container for the
	 * line data and may not be fully valid.
	 */
	target = grid_create(gd->sx, 0, 0);

	/*
	 * Loop over each source line.
	 */
	for (yy = 0; yy < gd->hsize + gd->sy; yy++) {
		gl = &gd->linedata[yy];
		if (gl->flags & GRID_LINE_DEAD)
			continue;

		/*
		 * Work out the width of this line. first is the width of the
		 * first character, at is the point at which the available
		 * width is hit, and width is the full line width.
		 */
		first = at = width = 0;
		if (~gl->flags & GRID_LINE_EXTENDED) {
			first = 1;
			width = gl->cellused;
			if (width > sx)
				at = sx;
			else
				at = width;
		} else {
			for (i = 0; i < gl->cellused; i++) {
				grid_get_cell1(gl, i, &gc);
				if (i == 0)
					first = gc.data.width;
				if (at == 0 && width + gc.data.width > sx)
					at = i;
				width += gc.data.width;
			}
		}

		/*
		 * If the line is exactly right or the first character is wider
		 * than the targe width, just move it across unchanged.
		 */
		if (width == sx || first > sx) {
			grid_reflow_move(target, gl);
			continue;
		}

		/*
		 * If the line is too big, it needs to be split, whether or not
		 * it was previously wrapped.
		 */
		if (width > sx) {
			grid_reflow_split(target, gd, sx, yy, at);
			continue;
		}

		/*
		 * If the line was previously wrapped, join as much as possible
		 * of the next line.
		 */
		if (gl->flags & GRID_LINE_WRAPPED)
			grid_reflow_join(target, gd, sx, yy, width, 0);
		else
			grid_reflow_move(target, gl);
	}

	/*
	 * Replace the old grid with the new.
	 */
	if (target->sy < gd->sy)
		grid_reflow_add(target, gd->sy - target->sy);
	gd->hsize = target->sy - gd->sy;
	if (gd->hscrolled > gd->hsize)
		gd->hscrolled = gd->hsize;
	free(gd->linedata);
	gd->linedata = target->linedata;
	free(target);
}
Ejemplo n.º 4
0
/* Reflow lines on grid to new width. */
void
grid_reflow(struct grid *gd, u_int sx, u_int *cursor)
{
	struct grid		*target;
	struct grid_line	*gl;
	struct grid_cell	 gc;
	u_int			 yy, cy, width, i, at, first;
	struct timeval		 start, tv;

	gettimeofday(&start, NULL);

	log_debug("%s: %u lines, new width %u", __func__, gd->hsize + gd->sy,
	    sx);
	cy = gd->hsize + (*cursor);

	/*
	 * Create a destination grid. This is just used as a container for the
	 * line data and may not be fully valid.
	 */
	target = grid_create(gd->sx, 0, 0);

	/*
	 * Loop over each source line.
	 */
	for (yy = 0; yy < gd->hsize + gd->sy; yy++) {
		gl = &gd->linedata[yy];
		if (gl->flags & GRID_LINE_DEAD)
			continue;

		/*
		 * Work out the width of this line. first is the width of the
		 * first character, at is the point at which the available
		 * width is hit, and width is the full line width.
		 */
		first = at = width = 0;
		if (~gl->flags & GRID_LINE_EXTENDED) {
			first = 1;
			width = gl->cellused;
			if (width > sx)
				at = sx;
			else
				at = width;
		} else {
			for (i = 0; i < gl->cellused; i++) {
				grid_get_cell1(gl, i, &gc);
				if (i == 0)
					first = gc.data.width;
				if (at == 0 && width + gc.data.width > sx)
					at = i;
				width += gc.data.width;
			}
		}

		/*
		 * If the line is exactly right or the first character is wider
		 * than the targe width, just move it across unchanged.
		 */
		if (width == sx || first > sx) {
			grid_reflow_move(target, gl);
			continue;
		}

		/*
		 * If the line is too big, it needs to be split, whether or not
		 * it was previously wrapped.
		 */
		if (width > sx) {
			grid_reflow_split(target, gd, sx, yy, at, &cy);
			continue;
		}

		/*
		 * If the line was previously wrapped, join as much as possible
		 * of the next line.
		 */
		if (gl->flags & GRID_LINE_WRAPPED)
			grid_reflow_join(target, gd, sx, yy, width, &cy, 0);
		else
			grid_reflow_move(target, gl);
	}

	/*
	 * Replace the old grid with the new.
	 */
	if (target->sy < gd->sy)
		grid_reflow_add(target, gd->sy - target->sy);
	gd->hsize = target->sy - gd->sy;
	free(gd->linedata);
	gd->linedata = target->linedata;
	free(target);

	/*
	 * Update scrolled and cursor positions.
	 */
	if (gd->hscrolled > gd->hsize)
		gd->hscrolled = gd->hsize;
	if (cy < gd->hsize)
		*cursor = 0;
	else
		*cursor = cy - gd->hsize;

	gettimeofday(&tv, NULL);
	timersub(&tv, &start, &tv);
	log_debug("%s: now %u lines (in %llu.%06u seconds)", __func__,
	    gd->hsize + gd->sy, (unsigned long long)tv.tv_sec,
	    (u_int)tv.tv_usec);
}