mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +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:
		
							
								
								
									
										69
									
								
								grid.c
									
									
									
									
									
								
							
							
						
						
									
										69
									
								
								grid.c
									
									
									
									
									
								
							@@ -1291,40 +1291,61 @@ grid_reflow(struct grid *gd, u_int sx)
 | 
				
			|||||||
	free(target);
 | 
						free(target);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Convert point position to offset from the start of the grid. */
 | 
					/* Convert to position based on wrapped lines. */
 | 
				
			||||||
u_int
 | 
					void
 | 
				
			||||||
grid_to_offset(struct grid *gd, u_int px, u_int py)
 | 
					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) {
 | 
						for (yy = 0; yy < py; yy++) {
 | 
				
			||||||
		px = UINT_MAX;
 | 
							if (gd->linedata[yy].flags & GRID_LINE_WRAPPED)
 | 
				
			||||||
		py = gd->hsize + gd->sy - 1;
 | 
								ax += gd->linedata[yy].cellused;
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								ax = 0;
 | 
				
			||||||
 | 
								ay++;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (px >= gd->linedata[yy].cellused)
 | 
				
			||||||
	for (yy = 0; yy < py; yy++)
 | 
							ax = UINT_MAX;
 | 
				
			||||||
		offset += gd->linedata[yy].cellused;
 | 
						else
 | 
				
			||||||
	if (px > gd->linedata[yy].cellused)
 | 
							ax += px;
 | 
				
			||||||
		px = gd->linedata[yy].cellused;
 | 
						*wx = ax;
 | 
				
			||||||
	return (offset + px);
 | 
						*wy = ay;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Convert offset from the start of the grid to point position. */
 | 
					/* Convert position based on wrapped lines back. */
 | 
				
			||||||
void
 | 
					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;
 | 
						u_int	yy, ax = 0, ay = 0;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	*px = *py = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (yy = 0; yy < gd->hsize + gd->sy - 1; yy++) {
 | 
						for (yy = 0; yy < gd->hsize + gd->sy - 1; yy++) {
 | 
				
			||||||
		if (offset <= gd->linedata[yy].cellused)
 | 
							if (ay == wy)
 | 
				
			||||||
			break;
 | 
								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
 | 
						 * yy is now 0 on the unwrapped line which contains wx. Walk forwards
 | 
				
			||||||
		*px = gd->linedata[yy].cellused;
 | 
						 * 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;
 | 
						*py = yy;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										8
									
								
								screen.c
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								screen.c
									
									
									
									
									
								
							@@ -464,17 +464,17 @@ 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)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	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;
 | 
						struct timeval	start, tv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gettimeofday(&start, NULL);
 | 
						gettimeofday(&start, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	offset = grid_to_offset(s->grid, cx, cy);
 | 
						grid_wrap_position(s->grid, cx, cy, &wx, &wy);
 | 
				
			||||||
	log_debug("%s: cursor %u,%u offset is %u", __func__, cx, cy, offset);
 | 
						log_debug("%s: cursor %u,%u is %u,%u", __func__, cx, cy, wx, wy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	grid_reflow(s->grid, new_x);
 | 
						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);
 | 
						log_debug("%s: new cursor is %u,%u", __func__, cx, cy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (cy >= s->grid->hsize) {
 | 
						if (cy >= s->grid->hsize) {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								tmux.h
									
									
									
									
									
								
							@@ -2101,8 +2101,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,
 | 
					void	 grid_duplicate_lines(struct grid *, u_int, struct grid *, u_int,
 | 
				
			||||||
	     u_int);
 | 
						     u_int);
 | 
				
			||||||
void	 grid_reflow(struct grid *, u_int);
 | 
					void	 grid_reflow(struct grid *, u_int);
 | 
				
			||||||
u_int	 grid_to_offset(struct grid *, u_int, u_int);
 | 
					void	 grid_wrap_position(struct grid *, u_int, u_int, u_int *, u_int *);
 | 
				
			||||||
void	 grid_from_offset(struct grid *, u_int, u_int *, u_int *);
 | 
					void	 grid_unwrap_position(struct grid *, u_int *, u_int *, 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 *);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user