mirror of
https://github.com/tmux/tmux.git
synced 2024-12-13 01:48:47 +00:00
Completely rewrite the reflow code to correctly handle double width
characters (previously they were not accounted for).
This commit is contained in:
parent
aeda2e5808
commit
533a5719c5
431
grid.c
431
grid.c
@ -43,22 +43,8 @@ static const struct grid_cell_entry grid_default_entry = {
|
|||||||
0, { .data = { 0, 8, 8, ' ' } }
|
0, { .data = { 0, 8, 8, ' ' } }
|
||||||
};
|
};
|
||||||
|
|
||||||
static void grid_expand_line(struct grid *, u_int, u_int, u_int);
|
|
||||||
static void grid_empty_line(struct grid *, u_int, u_int);
|
static void grid_empty_line(struct grid *, u_int, u_int);
|
||||||
|
|
||||||
static void grid_reflow_copy(struct grid_line *, u_int, struct grid_line *,
|
|
||||||
u_int, u_int);
|
|
||||||
static void grid_reflow_join(struct grid *, u_int *, struct grid_line *,
|
|
||||||
u_int);
|
|
||||||
static void grid_reflow_split(struct grid *, u_int *, struct grid_line *,
|
|
||||||
u_int, u_int);
|
|
||||||
static void grid_reflow_move(struct grid *, u_int *, struct grid_line *);
|
|
||||||
|
|
||||||
static size_t grid_string_cells_fg(const struct grid_cell *, int *);
|
|
||||||
static size_t grid_string_cells_bg(const struct grid_cell *, int *);
|
|
||||||
static void grid_string_cells_code(const struct grid_cell *,
|
|
||||||
const struct grid_cell *, char *, size_t, int);
|
|
||||||
|
|
||||||
/* Store cell in entry. */
|
/* Store cell in entry. */
|
||||||
static void
|
static void
|
||||||
grid_store_cell(struct grid_cell_entry *gce, const struct grid_cell *gc,
|
grid_store_cell(struct grid_cell_entry *gce, const struct grid_cell *gc,
|
||||||
@ -423,20 +409,11 @@ grid_peek_line(struct grid *gd, u_int py)
|
|||||||
return (&gd->linedata[py]);
|
return (&gd->linedata[py]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get cell for reading. */
|
/* Get cell from line. */
|
||||||
void
|
static void
|
||||||
grid_get_cell(struct grid *gd, u_int px, u_int py, struct grid_cell *gc)
|
grid_get_cell1(struct grid_line *gl, u_int px, struct grid_cell *gc)
|
||||||
{
|
{
|
||||||
struct grid_line *gl;
|
struct grid_cell_entry *gce = &gl->celldata[px];
|
||||||
struct grid_cell_entry *gce;
|
|
||||||
|
|
||||||
if (grid_check_y(gd, py) != 0 || px >= gd->linedata[py].cellsize) {
|
|
||||||
memcpy(gc, &grid_default_cell, sizeof *gc);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
gl = &gd->linedata[py];
|
|
||||||
gce = &gl->celldata[px];
|
|
||||||
|
|
||||||
if (gce->flags & GRID_FLAG_EXTENDED) {
|
if (gce->flags & GRID_FLAG_EXTENDED) {
|
||||||
if (gce->offset >= gl->extdsize)
|
if (gce->offset >= gl->extdsize)
|
||||||
@ -457,6 +434,17 @@ grid_get_cell(struct grid *gd, u_int px, u_int py, struct grid_cell *gc)
|
|||||||
utf8_set(&gc->data, gce->data.data);
|
utf8_set(&gc->data, gce->data.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get cell for reading. */
|
||||||
|
void
|
||||||
|
grid_get_cell(struct grid *gd, u_int px, u_int py, struct grid_cell *gc)
|
||||||
|
{
|
||||||
|
if (grid_check_y(gd, py) != 0 || px >= gd->linedata[py].cellsize) {
|
||||||
|
memcpy(gc, &grid_default_cell, sizeof *gc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return (grid_get_cell1(&gd->linedata[py], px, gc));
|
||||||
|
}
|
||||||
|
|
||||||
/* Set cell at relative position. */
|
/* Set cell at relative position. */
|
||||||
void
|
void
|
||||||
grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
|
grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
|
||||||
@ -953,164 +941,269 @@ grid_duplicate_lines(struct grid *dst, u_int dy, struct grid *src, u_int sy,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy a section of a line. */
|
/* Join line below onto this one. */
|
||||||
static void
|
static void
|
||||||
grid_reflow_copy(struct grid_line *dst_gl, u_int to, struct grid_line *src_gl,
|
grid_reflow_join(struct grid *gd, u_int sx, u_int yy, u_int width, u_int *cy)
|
||||||
u_int from, u_int to_copy)
|
|
||||||
{
|
{
|
||||||
struct grid_cell_entry *gce;
|
struct grid_line *gl = &gd->linedata[yy], *from;
|
||||||
u_int i, was;
|
struct grid_cell gc;
|
||||||
|
u_int lines, want, left, i, at = gl->cellused, line;
|
||||||
|
int wrapped = 1;
|
||||||
|
|
||||||
memcpy(&dst_gl->celldata[to], &src_gl->celldata[from],
|
lines = 0;
|
||||||
to_copy * sizeof *dst_gl->celldata);
|
for (;;) {
|
||||||
|
/*
|
||||||
|
* If this is now the last line, there is nothing more to be
|
||||||
|
* done.
|
||||||
|
*/
|
||||||
|
if (yy + lines == gd->hsize + gd->sy)
|
||||||
|
break;
|
||||||
|
line = yy + 1 + lines;
|
||||||
|
|
||||||
for (i = to; i < to + to_copy; i++) {
|
/* If the next line is empty, skip it. */
|
||||||
gce = &dst_gl->celldata[i];
|
if (~gd->linedata[line].flags & GRID_LINE_WRAPPED)
|
||||||
if (~gce->flags & GRID_FLAG_EXTENDED)
|
wrapped = 0;
|
||||||
|
if (gd->linedata[line].cellused == 0) {
|
||||||
|
if (!wrapped)
|
||||||
|
break;
|
||||||
continue;
|
continue;
|
||||||
was = gce->offset;
|
|
||||||
|
|
||||||
dst_gl->extddata = xreallocarray(dst_gl->extddata,
|
|
||||||
dst_gl->extdsize + 1, sizeof *dst_gl->extddata);
|
|
||||||
gce->offset = dst_gl->extdsize++;
|
|
||||||
memcpy(&dst_gl->extddata[gce->offset], &src_gl->extddata[was],
|
|
||||||
sizeof *dst_gl->extddata);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Join line data. */
|
|
||||||
static 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->cellused;
|
|
||||||
|
|
||||||
/* Work out how much to append. */
|
|
||||||
to_copy = src_gl->cellused;
|
|
||||||
if (to_copy > left)
|
|
||||||
to_copy = left;
|
|
||||||
ox = dst_gl->cellused;
|
|
||||||
nx = ox + to_copy;
|
|
||||||
|
|
||||||
/* Resize the destination line. */
|
|
||||||
dst_gl->celldata = xreallocarray(dst_gl->celldata, nx,
|
|
||||||
sizeof *dst_gl->celldata);
|
|
||||||
dst_gl->cellsize = dst_gl->cellused = 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->cellused > to_copy) {
|
|
||||||
dst_gl->flags |= GRID_LINE_WRAPPED;
|
|
||||||
|
|
||||||
src_gl->cellused -= to_copy;
|
|
||||||
grid_reflow_split(dst, py, src_gl, new_x, to_copy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Split line data. */
|
|
||||||
static void
|
|
||||||
grid_reflow_split(struct grid *dst, u_int *py, struct grid_line *src_gl,
|
|
||||||
u_int new_x, u_int offset)
|
|
||||||
{
|
|
||||||
struct grid_line *dst_gl = NULL;
|
|
||||||
u_int to_copy;
|
|
||||||
|
|
||||||
/* Loop and copy sections of the source line. */
|
|
||||||
while (src_gl->cellused > 0) {
|
|
||||||
/* Create new line. */
|
|
||||||
if (*py >= dst->hsize + dst->sy)
|
|
||||||
grid_scroll_history(dst, 8);
|
|
||||||
dst_gl = &dst->linedata[*py];
|
|
||||||
(*py)++;
|
|
||||||
|
|
||||||
/* How much should we copy? */
|
|
||||||
to_copy = new_x;
|
|
||||||
if (to_copy > src_gl->cellused)
|
|
||||||
to_copy = src_gl->cellused;
|
|
||||||
|
|
||||||
/* Expand destination line. */
|
|
||||||
dst_gl->celldata = xreallocarray(NULL, to_copy,
|
|
||||||
sizeof *dst_gl->celldata);
|
|
||||||
dst_gl->cellsize = dst_gl->cellused = to_copy;
|
|
||||||
dst_gl->flags |= GRID_LINE_WRAPPED;
|
|
||||||
|
|
||||||
/* Copy the data. */
|
|
||||||
grid_reflow_copy(dst_gl, 0, src_gl, offset, to_copy);
|
|
||||||
|
|
||||||
/* Move offset and reduce old line size. */
|
|
||||||
offset += to_copy;
|
|
||||||
src_gl->cellused -= to_copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Last line is not wrapped. */
|
|
||||||
if (dst_gl != NULL)
|
|
||||||
dst_gl->flags &= ~GRID_LINE_WRAPPED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Move line data. */
|
|
||||||
static void
|
|
||||||
grid_reflow_move(struct grid *dst, u_int *py, struct grid_line *src_gl)
|
|
||||||
{
|
|
||||||
struct grid_line *dst_gl;
|
|
||||||
|
|
||||||
/* Create new line. */
|
|
||||||
if (*py >= dst->hsize + dst->sy)
|
|
||||||
grid_scroll_history(dst, 8);
|
|
||||||
dst_gl = &dst->linedata[*py];
|
|
||||||
(*py)++;
|
|
||||||
|
|
||||||
/* Copy the old line. */
|
|
||||||
memcpy(dst_gl, src_gl, sizeof *dst_gl);
|
|
||||||
dst_gl->flags &= ~GRID_LINE_WRAPPED;
|
|
||||||
|
|
||||||
/* Clear old line. */
|
|
||||||
src_gl->celldata = NULL;
|
|
||||||
src_gl->extddata = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reflow lines from src grid into dst grid of width new_x. Returns number of
|
* Is the destination line now full? Copy the first character
|
||||||
* lines fewer in the visible area. The source grid is destroyed.
|
* separately because we need to leave "from" set to the last
|
||||||
|
* line if this line is full.
|
||||||
*/
|
*/
|
||||||
u_int
|
grid_get_cell1(&gd->linedata[line], 0, &gc);
|
||||||
grid_reflow(struct grid *dst, struct grid *src, u_int new_x)
|
if (width + gc.data.width > sx)
|
||||||
|
break;
|
||||||
|
width += gc.data.width;
|
||||||
|
grid_set_cell(gd, at, yy, &gc);
|
||||||
|
at++;
|
||||||
|
|
||||||
|
/* Join as much more as possible onto the current line. */
|
||||||
|
from = &gd->linedata[line];
|
||||||
|
for (want = 1; want < from->cellused; want++) {
|
||||||
|
grid_get_cell1(from, want, &gc);
|
||||||
|
if (width + gc.data.width > sx)
|
||||||
|
break;
|
||||||
|
width += gc.data.width;
|
||||||
|
|
||||||
|
grid_set_cell(gd, at, yy, &gc);
|
||||||
|
at++;
|
||||||
|
}
|
||||||
|
lines++;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If this line wasn't wrapped or we didn't consume the entire
|
||||||
|
* line, don't try to join any further lines.
|
||||||
|
*/
|
||||||
|
if (!wrapped || want != from->cellused || width == sx)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (lines == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we didn't consume the entire final line, then remove what we did
|
||||||
|
* consume. If we consumed the entire line and it wasn't wrapped,
|
||||||
|
* remove the wrap flag from this line.
|
||||||
|
*/
|
||||||
|
left = from->cellused - want;
|
||||||
|
if (left != 0) {
|
||||||
|
grid_move_cells(gd, 0, want, yy + lines, left, 8);
|
||||||
|
from->cellsize = from->cellused = left;
|
||||||
|
lines--;
|
||||||
|
} else if (!wrapped)
|
||||||
|
gl->flags &= ~GRID_LINE_WRAPPED;
|
||||||
|
|
||||||
|
/* Remove the lines that were completely consumed. */
|
||||||
|
if (lines != 0) {
|
||||||
|
if (yy + lines != gd->hsize + gd->sy) {
|
||||||
|
memmove(&gd->linedata[yy + 1],
|
||||||
|
&gd->linedata[yy + lines + 1],
|
||||||
|
((gd->hsize + gd->sy) - (yy + lines + 1)) *
|
||||||
|
(sizeof *gd->linedata));
|
||||||
|
}
|
||||||
|
if (gd->hsize >= lines)
|
||||||
|
gd->hsize -= lines;
|
||||||
|
else {
|
||||||
|
lines -= gd->hsize;
|
||||||
|
gd->hsize = 0;
|
||||||
|
for (i = 1; i < lines + 1; i++)
|
||||||
|
grid_empty_line(gd, gd->hsize + gd->sy - i, 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adjust cursor and scroll positions. */
|
||||||
|
if (*cy > yy + lines)
|
||||||
|
*cy -= lines;
|
||||||
|
else if (*cy > yy)
|
||||||
|
*cy = yy;
|
||||||
|
if (gd->hscrolled > yy + lines)
|
||||||
|
gd->hscrolled -= lines;
|
||||||
|
else if (gd->hscrolled > yy)
|
||||||
|
gd->hscrolled = yy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Split this line into several new ones */
|
||||||
|
static void
|
||||||
|
grid_reflow_split(struct grid *gd, u_int sx, u_int yy, u_int at, u_int *cy)
|
||||||
{
|
{
|
||||||
u_int py, sy, line;
|
struct grid_line *gl = &gd->linedata[yy];
|
||||||
int previous_wrapped;
|
struct grid_cell gc;
|
||||||
struct grid_line *src_gl;
|
u_int line, lines, width, i, used = gl->cellused, xx;
|
||||||
|
int flags = gl->flags;
|
||||||
|
|
||||||
py = 0;
|
/* How many lines do we need to insert? We know we need at least one. */
|
||||||
sy = src->sy;
|
if (~gl->flags & GRID_LINE_EXTENDED)
|
||||||
|
lines = (gl->cellused - 1) / sx;
|
||||||
|
else {
|
||||||
|
lines = 1;
|
||||||
|
width = 0;
|
||||||
|
for (i = at; i < used; i++) {
|
||||||
|
grid_get_cell1(gl, i, &gc);
|
||||||
|
if (width + gc.data.width > sx) {
|
||||||
|
lines++;
|
||||||
|
width = 0;
|
||||||
|
}
|
||||||
|
width += gc.data.width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
previous_wrapped = 0;
|
/* Trim the original line size. */
|
||||||
for (line = 0; line < sy + src->hsize; line++) {
|
gl->cellsize = gl->cellused = at;
|
||||||
src_gl = src->linedata + line;
|
gl->flags |= GRID_LINE_WRAPPED;
|
||||||
if (!previous_wrapped) {
|
|
||||||
/* Wasn't wrapped. If smaller, move to destination. */
|
/* Insert new lines. */
|
||||||
if (src_gl->cellused <= new_x)
|
gd->linedata = xreallocarray(gd->linedata, gd->hsize + gd->sy + lines,
|
||||||
grid_reflow_move(dst, &py, src_gl);
|
sizeof *gd->linedata);
|
||||||
|
memmove(&gd->linedata[yy + lines + 1], &gd->linedata[yy + 1],
|
||||||
|
((gd->hsize + gd->sy) - (yy + 1)) * (sizeof *gd->linedata));
|
||||||
|
gd->hsize += lines;
|
||||||
|
for (i = 0; i < lines; i++)
|
||||||
|
grid_empty_line(gd, yy + 1 + i, 8);
|
||||||
|
gl = &gd->linedata[yy];
|
||||||
|
|
||||||
|
/* Copy sections from the original line. */
|
||||||
|
line = yy + 1;
|
||||||
|
width = 0;
|
||||||
|
xx = 0;
|
||||||
|
for (i = at; i < used; i++) {
|
||||||
|
grid_get_cell1(gl, i, &gc);
|
||||||
|
if (width + gc.data.width > sx) {
|
||||||
|
gd->linedata[line].flags |= GRID_LINE_WRAPPED;
|
||||||
|
|
||||||
|
line++;
|
||||||
|
width = 0;
|
||||||
|
xx = 0;
|
||||||
|
}
|
||||||
|
width += gc.data.width;
|
||||||
|
grid_set_cell(gd, xx, line, &gc);
|
||||||
|
xx++;
|
||||||
|
}
|
||||||
|
if (flags & GRID_LINE_WRAPPED)
|
||||||
|
gd->linedata[line].flags |= GRID_LINE_WRAPPED;
|
||||||
|
|
||||||
|
/* Adjust the cursor and scroll positions. */
|
||||||
|
if (yy <= *cy)
|
||||||
|
(*cy) += lines;
|
||||||
|
if (yy <= gd->hscrolled)
|
||||||
|
gd->hscrolled += lines;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the original line had the wrapped flag and there is still space
|
||||||
|
* in the last new line, try to join with the next lines.
|
||||||
|
*/
|
||||||
|
if (width < sx && (flags & GRID_LINE_WRAPPED))
|
||||||
|
grid_reflow_join(gd, sx, line, width, cy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reflow lines on grid to new width. */
|
||||||
|
void
|
||||||
|
grid_reflow(struct grid *gd, u_int sx, u_int *cursor)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Loop over lines from top to bottom. The size may change during the
|
||||||
|
* loop, but it is OK because we are always adding or removing lines
|
||||||
|
* below the current one.
|
||||||
|
*/
|
||||||
|
for (yy = 0; yy < gd->hsize + gd->sy; yy++) {
|
||||||
|
gl = &gd->linedata[yy];
|
||||||
|
|
||||||
|
/* Work out the width of this line. */
|
||||||
|
first = at = width = 0;
|
||||||
|
if (~gl->flags & GRID_LINE_EXTENDED) {
|
||||||
|
first = 1;
|
||||||
|
width = gl->cellused;
|
||||||
|
if (width > sx)
|
||||||
|
at = sx;
|
||||||
else
|
else
|
||||||
grid_reflow_split(dst, &py, src_gl, new_x, 0);
|
at = width;
|
||||||
} else {
|
} else {
|
||||||
/* Previous was wrapped. Try to join. */
|
for (i = 0; i < gl->cellused; i++) {
|
||||||
grid_reflow_join(dst, &py, src_gl, new_x);
|
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;
|
||||||
}
|
}
|
||||||
previous_wrapped = (src_gl->flags & GRID_LINE_WRAPPED);
|
|
||||||
|
|
||||||
/* This is where we started scrolling. */
|
|
||||||
if (line == sy + src->hsize - src->hscrolled - 1)
|
|
||||||
dst->hscrolled = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
grid_destroy(src);
|
/*
|
||||||
|
* If the line is exactly right, there is no need to do
|
||||||
|
* anything.
|
||||||
|
*/
|
||||||
|
if (width == sx)
|
||||||
|
continue;
|
||||||
|
|
||||||
if (py > sy)
|
/*
|
||||||
return (0);
|
* If the first character is wider than the target width, there
|
||||||
return (sy - py);
|
* is no point in trying to do anything.
|
||||||
|
*/
|
||||||
|
if (first > sx)
|
||||||
|
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(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(gd, sx, yy, width, &cy);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
@ -378,6 +378,7 @@ screen_write_copy(struct screen_write_ctx *ctx, struct screen *src, u_int px,
|
|||||||
gc.bg = mgc->bg;
|
gc.bg = mgc->bg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (xx + gc.data.width <= px + nx)
|
||||||
screen_write_cell(ctx, &gc);
|
screen_write_cell(ctx, &gc);
|
||||||
}
|
}
|
||||||
cy++;
|
cy++;
|
||||||
@ -410,6 +411,8 @@ screen_write_fast_copy(struct screen_write_ctx *ctx, struct screen *src,
|
|||||||
if (xx >= gd->linedata[yy].cellsize)
|
if (xx >= gd->linedata[yy].cellsize)
|
||||||
break;
|
break;
|
||||||
grid_get_cell(gd, xx, yy, &gc);
|
grid_get_cell(gd, xx, yy, &gc);
|
||||||
|
if (xx + gc.data.width > px + nx)
|
||||||
|
break;
|
||||||
if (!grid_cells_equal(&gc, &grid_default_cell))
|
if (!grid_cells_equal(&gc, &grid_default_cell))
|
||||||
grid_view_set_cell(ctx->s->grid, cx, cy, &gc);
|
grid_view_set_cell(ctx->s->grid, cx, cy, &gc);
|
||||||
cx++;
|
cx++;
|
||||||
|
11
screen.c
11
screen.c
@ -470,14 +470,5 @@ screen_select_cell(struct screen *s, struct grid_cell *dst,
|
|||||||
static void
|
static void
|
||||||
screen_reflow(struct screen *s, u_int new_x)
|
screen_reflow(struct screen *s, u_int new_x)
|
||||||
{
|
{
|
||||||
struct grid *old = s->grid;
|
grid_reflow(s->grid, new_x, &s->cy);
|
||||||
u_int change;
|
|
||||||
|
|
||||||
s->grid = grid_create(old->sx, old->sy, old->hlimit);
|
|
||||||
|
|
||||||
change = grid_reflow(s->grid, old, new_x);
|
|
||||||
if (change < s->cy)
|
|
||||||
s->cy -= change;
|
|
||||||
else
|
|
||||||
s->cy = 0;
|
|
||||||
}
|
}
|
||||||
|
2
tmux.h
2
tmux.h
@ -1996,7 +1996,7 @@ char *grid_string_cells(struct grid *, u_int, u_int, u_int,
|
|||||||
struct grid_cell **, int, int, int);
|
struct grid_cell **, int, int, int);
|
||||||
void grid_duplicate_lines(struct grid *, u_int, struct grid *, u_int,
|
void grid_duplicate_lines(struct grid *, u_int, struct grid *, u_int,
|
||||||
u_int);
|
u_int);
|
||||||
u_int grid_reflow(struct grid *, struct grid *, u_int);
|
void grid_reflow(struct grid *, u_int, u_int *);
|
||||||
|
|
||||||
/* grid-view.c */
|
/* grid-view.c */
|
||||||
void grid_view_get_cell(struct grid *, u_int, u_int, struct grid_cell *);
|
void grid_view_get_cell(struct grid *, u_int, u_int, struct grid_cell *);
|
||||||
|
Loading…
Reference in New Issue
Block a user