예제 #1
0
/* Insert nx characters. */
void
screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx)
{
	struct screen	*s = ctx->s;
	struct tty_ctx	 ttyctx;

	if (nx == 0)
		nx = 1;

	if (nx > screen_size_x(s) - s->cx)
		nx = screen_size_x(s) - s->cx;
	if (nx == 0)
		return;

	screen_write_initctx(ctx, &ttyctx, 0);

	if (s->cx <= screen_size_x(s) - 1)
		grid_view_insert_cells(s->grid, s->cx, s->cy, nx);

	ttyctx.num = nx;
	tty_write(tty_cmd_insertcharacter, &ttyctx);
}
예제 #2
0
/* 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;
	u_int			 sx = screen_size_x(s), sy = screen_size_y(s);
	struct grid_line	*gl;
	struct grid_cell 	 tmp_gc, now_gc;
	struct grid_cell_entry	*gce;
	int			 insert, skip, selected, wrapped = 0;

	ctx->cells++;

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

	/*
	 * 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 > sx || (s->cx != sx && s->cx > sx - width))))
		return;

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

	/* Initialise the redraw context. */
	screen_write_initctx(ctx, &ttyctx);

	/* If in insert mode, make space for the cells. */
	if (s->mode & MODE_INSERT) {
		if (s->cx <= sx - width) {
			screen_write_flush(ctx);
			xx = sx - s->cx - width;
			grid_view_insert_cells(s->grid, s->cx, s->cy, xx, 8);
		}
		insert = 1;
	} else
		insert = 0;
	skip = !insert;

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

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

	/* Handle overwriting of UTF-8 characters. */
	gl = &s->grid->linedata[s->grid->hsize + s->cy];
	if (gl->flags & GRID_LINE_EXTENDED) {
		grid_view_get_cell(gd, s->cx, s->cy, &now_gc);
		if (screen_write_overwrite(ctx, &now_gc, width))
			skip = 0;
	}

	/*
	 * 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++) {
		grid_view_set_cell(gd, xx, s->cy, &screen_write_pad_cell);
		skip = 0;
	}

	/* If no change, do not draw. */
	if (skip) {
		if (s->cx >= gl->cellsize)
			skip = grid_cells_equal(gc, &grid_default_cell);
		else {
			gce = &gl->celldata[s->cx];
			if (gce->flags & GRID_FLAG_EXTENDED)
				skip = 0;
			else if (gc->flags != gce->flags)
				skip = 0;
			else if (gc->attr != gce->data.attr)
				skip = 0;
			else if (gc->fg != gce->data.fg)
				skip = 0;
			else if (gc->bg != gce->data.bg)
				skip = 0;
			else if (gc->data.width != 1)
				skip = 0;
			else if (gce->data.data != gc->data.data[0])
				skip = 0;
		}
	}

	/* Update the selection the flag and set the cell. */
	selected = screen_check_selection(s, s->cx, s->cy);
	if (selected && ~gc->flags & GRID_FLAG_SELECTED) {
		skip = 0;
		memcpy(&tmp_gc, gc, sizeof tmp_gc);
		tmp_gc.flags |= GRID_FLAG_SELECTED;
		grid_view_set_cell(gd, s->cx, s->cy, &tmp_gc);
	} else if (!selected && gc->flags & GRID_FLAG_SELECTED) {
		skip = 0;
		memcpy(&tmp_gc, gc, sizeof tmp_gc);
		tmp_gc.flags &= ~GRID_FLAG_SELECTED;
		grid_view_set_cell(gd, s->cx, s->cy, &tmp_gc);
	} else if (!skip)
		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 <= sx - last - width)
		s->cx += width;
	else
		s->cx = sx - last;

	/* Create space for character in insert mode. */
	if (insert) {
		ttyctx.num = width;
		tty_write(tty_cmd_insertcharacter, &ttyctx);
	}

	/* Write to the screen. */
	if (selected) {
		screen_write_flush(ctx);
		screen_select_cell(s, &tmp_gc, gc);
		ttyctx.cell = &tmp_gc;
		tty_write(tty_cmd_cell, &ttyctx);
		ctx->written++;
	} else if (!skip) {
		if (wrapped) {
			ttyctx.cell = gc;
			tty_write(tty_cmd_cell, &ttyctx);
			ctx->written++;
		} else {
			/*
			 * If wp is NULL, we are not updating the terminal and
			 * don't care about actually writing the cells
			 * (tty_write will just return). So don't even bother
			 * allocating the dirty array.
			 */
			if (ctx->wp != NULL && s->dirty == NULL) {
				log_debug("%s: allocating %u bits", __func__,
				    s->dirtysize);
				s->dirty = bit_alloc(s->dirtysize);
			}
			if (s->dirty != NULL) {
				bit_set(s->dirty, screen_dirty_bit(s,
				    ttyctx.ocx, ttyctx.ocy));
				ctx->dirty++;
			}
		}
	} else
		ctx->skipped++;
}