コード例 #1
0
ファイル: grid.c プロジェクト: sakushin/tmux
/* Convert cells into a string. */
char *
grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx)
{
	const struct grid_cell	*gc;
	struct utf8_data	 ud;
	char			*buf;
	size_t			 len, off;
	u_int			 xx;

	GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx);

	len = 128;
	buf = xmalloc(len);
	off = 0;

	for (xx = px; xx < px + nx; xx++) {
		gc = grid_peek_cell(gd, xx, py);
		if (gc->flags & GRID_FLAG_PADDING)
			continue;
		grid_cell_get(gc, &ud);

		while (len < off + ud.size + 1) {
			buf = xrealloc(buf, 2, len);
			len *= 2;
		}

		memcpy(buf + off, ud.data, ud.size);
		off += ud.size;
	}

	while (off > 0 && buf[off - 1] == ' ')
		off--;
	buf[off] = '\0';
	return (buf);
}
コード例 #2
0
/* Combine a UTF-8 zero-width character onto the previous. */
int
screen_write_combine(struct screen_write_ctx *ctx, const struct utf8_data *ud)
{
	struct screen		*s = ctx->s;
	struct grid		*gd = s->grid;
	struct grid_cell	*gc;
	struct utf8_data	 ud1;

	/* Can't combine if at 0. */
	if (s->cx == 0)
		return (-1);

	/* Empty data is out. */
	if (ud->size == 0)
		fatalx("UTF-8 data empty");

	/* Retrieve the previous cell. */
	gc = grid_view_get_cell(gd, s->cx - 1, s->cy);
	grid_cell_get(gc, &ud1);

	/* Check there is enough space. */
	if (ud1.size + ud->size > sizeof ud1.data)
		return (-1);

	/* Append the data and set the cell. */
	memcpy(ud1.data + ud1.size, ud->data, ud->size);
	ud1.size += ud->size;
	grid_cell_set(gc, &ud1);

	return (0);
}
コード例 #3
0
ファイル: screen-write.c プロジェクト: SylvestreG/bitrig
/* Copy from another screen. */
void
screen_write_copy(struct screen_write_ctx *ctx,
    struct screen *src, u_int px, u_int py, u_int nx, u_int ny)
{
	struct screen		*s = ctx->s;
	struct grid		*gd = src->grid;
	struct grid_line	*gl;
	const struct grid_cell	*gc;
	struct utf8_data	 ud;
	u_int		 	 xx, yy, cx, cy, ax, bx;

	cx = s->cx;
	cy = s->cy;
	for (yy = py; yy < py + ny; yy++) {
		gl = &gd->linedata[yy];
		if (yy < gd->hsize + gd->sy) {
			/*
			 * Find start and end position and copy between
			 * them. Limit to the real end of the line then use a
			 * clear EOL only if copying to the end, otherwise
			 * could overwrite whatever is there already.
			 */
			if (px > gl->cellsize)
				ax = gl->cellsize;
			else
				ax = px;
			if (px + nx == gd->sx && px + nx > gl->cellsize)
				bx = gl->cellsize;
			else
				bx = px + nx;

			for (xx = ax; xx < bx; xx++) {
				if (xx >= gl->cellsize)
					gc = &grid_default_cell;
				else
					gc = &gl->celldata[xx];
				grid_cell_get(gc, &ud);
				screen_write_cell(ctx, gc);
			}
			if (px + nx == gd->sx && px + nx > gl->cellsize)
				screen_write_clearendofline(ctx);
		} else
			screen_write_clearline(ctx);
		cy++;
		screen_write_cursormove(ctx, cx, cy);
	}
}
コード例 #4
0
ファイル: grid.c プロジェクト: SylvestreG/bitrig
/* Convert cells into a string. */
char *
grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
    struct grid_cell **lastgc, int with_codes, int escape_c0, int trim)
{
	const struct grid_cell	*gc;
	static struct grid_cell	 lastgc1;
	struct utf8_data	 ud;
	const char*		 data;
	char			*buf, code[128];
	size_t			 len, off, size, codelen;
	u_int			 xx;
	const struct grid_line	*gl;

	if (lastgc != NULL && *lastgc == NULL) {
		memcpy(&lastgc1, &grid_default_cell, sizeof lastgc1);
		*lastgc = &lastgc1;
	}

	len = 128;
	buf = xmalloc(len);
	off = 0;

	gl = grid_peek_line(gd, py);
	for (xx = px; xx < px + nx; xx++) {
		if (gl == NULL || xx >= gl->cellsize)
			break;
		gc = &gl->celldata[xx];
		if (gc->flags & GRID_FLAG_PADDING)
			continue;
		grid_cell_get(gc, &ud);

		if (with_codes) {
			grid_string_cells_code(*lastgc, gc, code, sizeof code,
			    escape_c0);
			codelen = strlen(code);
			memcpy(*lastgc, gc, sizeof *gc);
		} else
			codelen = 0;

		data = ud.data;
		size = ud.size;
		if (escape_c0 && size == 1 && *data == '\\') {
			data = "\\\\";
			size = 2;
		}

		while (len < off + size + codelen + 1) {
			buf = xrealloc(buf, 2, len);
			len *= 2;
		}

		if (codelen != 0) {
			memcpy(buf + off, code, codelen);
			off += codelen;
		}
		memcpy(buf + off, data, size);
		off += size;
	}

	if (trim) {
		while (off > 0 && buf[off - 1] == ' ')
			off--;
	}
	buf[off] = '\0';

	return (buf);
}
コード例 #5
0
ファイル: screen-write.c プロジェクト: SylvestreG/bitrig
/* Write cell data. */
void
screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
{
	struct screen		*s = ctx->s;
	struct grid		*gd = s->grid;
	struct tty_ctx		 ttyctx;
	u_int		 	 width, xx, last;
	struct grid_cell 	 tmp_gc, *tmp_gcp;
	struct utf8_data	 ud;
	int			 insert;

	/* Ignore padding. */
	if (gc->flags & GRID_FLAG_PADDING)
		return;
	width = grid_cell_width(gc);

	/*
	 * If this is a wide character and there is no room on the screen, for
	 * the entire character, don't print it.
	 */
	if (!(s->mode & MODE_WRAP)
	    && (width > 1 && (width > screen_size_x(s) ||
		(s->cx != screen_size_x(s)
		 && s->cx > screen_size_x(s) - width))))
		return;

	/*
	 * If the width is zero, combine onto the previous character, if
	 * there is space.
	 */
	if (width == 0) {
		grid_cell_get(gc, &ud);
		if (screen_write_combine(ctx, &ud) == 0) {
			screen_write_initctx(ctx, &ttyctx, 0);
			tty_write(tty_cmd_utf8character, &ttyctx);
		}
		return;
	}

	/* Initialise the redraw context, saving the last cell. */
	screen_write_initctx(ctx, &ttyctx, 1);

	/* If in insert mode, make space for the cells. */
	if ((s->mode & MODE_INSERT) && s->cx <= screen_size_x(s) - width) {
		xx = screen_size_x(s) - s->cx - width;
		grid_move_cells(s->grid, s->cx + width, s->cx, s->cy, xx);
		insert = 1;
	} else
		insert = 0;

	/* Check this will fit on the current line and wrap if not. */
	if ((s->mode & MODE_WRAP) && s->cx > screen_size_x(s) - width) {
		screen_write_linefeed(ctx, 1);
		s->cx = 0;	/* carriage return */
	}

	/* Sanity check cursor position. */
	if (s->cx > screen_size_x(s) - width || s->cy > screen_size_y(s) - 1)
		return;

	/* Handle overwriting of UTF-8 characters. */
	screen_write_overwrite(ctx, width);

	/*
	 * If the new character is UTF-8 wide, fill in padding cells. Have
	 * already ensured there is enough room.
	 */
	for (xx = s->cx + 1; xx < s->cx + width; xx++) {
		tmp_gcp = grid_view_get_cell(gd, xx, s->cy);
		if (tmp_gcp != NULL)
			tmp_gcp->flags |= GRID_FLAG_PADDING;
	}

	/* Set the cell. */
	grid_view_set_cell(gd, s->cx, s->cy, gc);

	/*
	 * Move the cursor. If not wrapping, stick at the last character and
	 * replace it.
	 */
	last = !(s->mode & MODE_WRAP);
	if (s->cx <= screen_size_x(s) - last - width)
		s->cx += width;
	else
		s->cx = screen_size_x(s) - last;

	/* Draw to the screen if necessary. */
	if (insert) {
		ttyctx.num = width;
		tty_write(tty_cmd_insertcharacter, &ttyctx);
	}
	if (screen_check_selection(s, s->cx - width, s->cy)) {
		memcpy(&tmp_gc, &s->sel.cell, sizeof tmp_gc);
		grid_cell_get(gc, &ud);
		grid_cell_set(&tmp_gc, &ud);
		tmp_gc.flags = gc->flags & ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
		tmp_gc.flags |= s->sel.cell.flags &
		    (GRID_FLAG_FG256|GRID_FLAG_BG256);
		ttyctx.cell = &tmp_gc;
		tty_write(tty_cmd_cell, &ttyctx);
	} else {
		ttyctx.cell = gc;
		tty_write(tty_cmd_cell, &ttyctx);
	}
}