mirror of
https://github.com/tmux/tmux.git
synced 2025-01-13 11:58:51 +00:00
Store and restore cursor across reflow by working out a position based
on unwrapped lines, rather than a grid offset. Fixes problems reported by Thomas Sattler and Paul de Weerd.
This commit is contained in:
parent
6d071c468c
commit
bbcfee362f
69
grid.c
69
grid.c
@ -1291,40 +1291,61 @@ grid_reflow(struct grid *gd, u_int sx)
|
||||
free(target);
|
||||
}
|
||||
|
||||
/* Convert point position to offset from the start of the grid. */
|
||||
u_int
|
||||
grid_to_offset(struct grid *gd, u_int px, u_int py)
|
||||
/* Convert to position based on wrapped lines. */
|
||||
void
|
||||
grid_wrap_position(struct grid *gd, u_int px, u_int py, u_int *wx, u_int *wy)
|
||||
{
|
||||
u_int yy, offset = 0;
|
||||
u_int ax = 0, ay = 0, yy;
|
||||
|
||||
if (py > gd->hsize + gd->sy - 1) {
|
||||
px = UINT_MAX;
|
||||
py = gd->hsize + gd->sy - 1;
|
||||
for (yy = 0; yy < py; yy++) {
|
||||
if (gd->linedata[yy].flags & GRID_LINE_WRAPPED)
|
||||
ax += gd->linedata[yy].cellused;
|
||||
else {
|
||||
ax = 0;
|
||||
ay++;
|
||||
}
|
||||
}
|
||||
|
||||
for (yy = 0; yy < py; yy++)
|
||||
offset += gd->linedata[yy].cellused;
|
||||
if (px > gd->linedata[yy].cellused)
|
||||
px = gd->linedata[yy].cellused;
|
||||
return (offset + px);
|
||||
if (px >= gd->linedata[yy].cellused)
|
||||
ax = UINT_MAX;
|
||||
else
|
||||
ax += px;
|
||||
*wx = ax;
|
||||
*wy = ay;
|
||||
}
|
||||
|
||||
/* Convert offset from the start of the grid to point position. */
|
||||
/* Convert position based on wrapped lines back. */
|
||||
void
|
||||
grid_from_offset(struct grid *gd, u_int offset, u_int *px, u_int *py)
|
||||
grid_unwrap_position(struct grid *gd, u_int *px, u_int *py, u_int wx, u_int wy)
|
||||
{
|
||||
u_int yy;
|
||||
|
||||
*px = *py = 0;
|
||||
u_int yy, ax = 0, ay = 0;
|
||||
|
||||
for (yy = 0; yy < gd->hsize + gd->sy - 1; yy++) {
|
||||
if (offset <= gd->linedata[yy].cellused)
|
||||
if (ay == wy)
|
||||
break;
|
||||
offset -= gd->linedata[yy].cellused;
|
||||
if (gd->linedata[yy].flags & GRID_LINE_WRAPPED)
|
||||
ax += gd->linedata[yy].cellused;
|
||||
else {
|
||||
ax = 0;
|
||||
ay++;
|
||||
}
|
||||
}
|
||||
if (offset < gd->linedata[yy].cellused)
|
||||
*px = offset;
|
||||
else
|
||||
*px = gd->linedata[yy].cellused;
|
||||
|
||||
/*
|
||||
* yy is now 0 on the unwrapped line which contains wx. Walk forwards
|
||||
* until we find the end or the line now containing wx.
|
||||
*/
|
||||
if (wx == UINT_MAX) {
|
||||
while (gd->linedata[yy].flags & GRID_LINE_WRAPPED)
|
||||
yy++;
|
||||
wx = gd->linedata[yy].cellused;
|
||||
} else {
|
||||
while (gd->linedata[yy].flags & GRID_LINE_WRAPPED) {
|
||||
if (wx < gd->linedata[yy].cellused)
|
||||
break;
|
||||
wx -= gd->linedata[yy].cellused;
|
||||
yy++;
|
||||
}
|
||||
}
|
||||
*px = wx;
|
||||
*py = yy;
|
||||
}
|
||||
|
8
screen.c
8
screen.c
@ -463,17 +463,17 @@ screen_select_cell(struct screen *s, struct grid_cell *dst,
|
||||
static void
|
||||
screen_reflow(struct screen *s, u_int new_x)
|
||||
{
|
||||
u_int offset, cx = s->cx, cy = s->grid->hsize + s->cy;
|
||||
u_int cx = s->cx, cy = s->grid->hsize + s->cy, wx, wy;
|
||||
struct timeval start, tv;
|
||||
|
||||
gettimeofday(&start, NULL);
|
||||
|
||||
offset = grid_to_offset(s->grid, cx, cy);
|
||||
log_debug("%s: cursor %u,%u offset is %u", __func__, cx, cy, offset);
|
||||
grid_wrap_position(s->grid, cx, cy, &wx, &wy);
|
||||
log_debug("%s: cursor %u,%u is %u,%u", __func__, cx, cy, wx, wy);
|
||||
|
||||
grid_reflow(s->grid, new_x);
|
||||
|
||||
grid_from_offset(s->grid, offset, &cx, &cy);
|
||||
grid_unwrap_position(s->grid, &cx, &cy, wx, wy);
|
||||
log_debug("%s: new cursor is %u,%u", __func__, cx, cy);
|
||||
|
||||
if (cy >= s->grid->hsize) {
|
||||
|
4
tmux.h
4
tmux.h
@ -2103,8 +2103,8 @@ char *grid_string_cells(struct grid *, u_int, u_int, u_int,
|
||||
void grid_duplicate_lines(struct grid *, u_int, struct grid *, u_int,
|
||||
u_int);
|
||||
void grid_reflow(struct grid *, u_int);
|
||||
u_int grid_to_offset(struct grid *, u_int, u_int);
|
||||
void grid_from_offset(struct grid *, u_int, u_int *, u_int *);
|
||||
void grid_wrap_position(struct grid *, u_int, u_int, u_int *, u_int *);
|
||||
void grid_unwrap_position(struct grid *, u_int *, u_int *, u_int, u_int);
|
||||
|
||||
/* grid-view.c */
|
||||
void grid_view_get_cell(struct grid *, u_int, u_int, struct grid_cell *);
|
||||
|
Loading…
Reference in New Issue
Block a user