mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 09:17:31 +00:00 
			
		
		
		
	Rework reflow code so it does not do so much allocation which should be
faster with large histories.
This commit is contained in:
		
							
								
								
									
										153
									
								
								grid.c
									
									
									
									
									
								
							
							
						
						
									
										153
									
								
								grid.c
									
									
									
									
									
								
							@@ -70,6 +70,11 @@ grid_check_y(struct grid *gd, u_int py)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void	grid_reflow_join(struct grid *, u_int *, struct grid_line *, u_int);
 | 
				
			||||||
 | 
					void	grid_reflow_split(struct grid *, u_int *, struct grid_line *, u_int,
 | 
				
			||||||
 | 
						    u_int);
 | 
				
			||||||
 | 
					void	grid_reflow_move(struct grid *, u_int *, struct grid_line *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Create a new grid. */
 | 
					/* Create a new grid. */
 | 
				
			||||||
struct grid *
 | 
					struct grid *
 | 
				
			||||||
grid_create(u_int sx, u_int sy, u_int hlimit)
 | 
					grid_create(u_int sx, u_int sy, u_int hlimit)
 | 
				
			||||||
@@ -461,43 +466,135 @@ grid_duplicate_lines(
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Join line data. */
 | 
				
			||||||
 | 
					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->cellsize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Work out how much to append. */
 | 
				
			||||||
 | 
						to_copy = src_gl->cellsize;
 | 
				
			||||||
 | 
						if (to_copy > left)
 | 
				
			||||||
 | 
							to_copy = left;
 | 
				
			||||||
 | 
						ox = dst_gl->cellsize;
 | 
				
			||||||
 | 
						nx = ox + to_copy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Resize the destination line. */
 | 
				
			||||||
 | 
						dst_gl->celldata = xrealloc(dst_gl->celldata, nx,
 | 
				
			||||||
 | 
						    sizeof *dst_gl->celldata);
 | 
				
			||||||
 | 
						dst_gl->cellsize = nx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Append as much as possible. */
 | 
				
			||||||
 | 
						memcpy(&dst_gl->celldata[ox], &src_gl->celldata[0],
 | 
				
			||||||
 | 
						    to_copy * sizeof src_gl->celldata[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* If there is any left in the source, split it. */
 | 
				
			||||||
 | 
						if (src_gl->cellsize > to_copy) {
 | 
				
			||||||
 | 
							dst_gl->flags |= GRID_LINE_WRAPPED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							src_gl->cellsize -= to_copy;
 | 
				
			||||||
 | 
							grid_reflow_split(dst, py, src_gl, new_x, to_copy);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Split line data. */
 | 
				
			||||||
 | 
					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->cellsize > 0) {
 | 
				
			||||||
 | 
							/* Create new line. */
 | 
				
			||||||
 | 
							if (*py >= dst->hsize + dst->sy)
 | 
				
			||||||
 | 
								grid_scroll_history(dst);
 | 
				
			||||||
 | 
							dst_gl = &dst->linedata[*py];
 | 
				
			||||||
 | 
							(*py)++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* How much should we copy? */
 | 
				
			||||||
 | 
							to_copy = new_x;
 | 
				
			||||||
 | 
							if (to_copy > src_gl->cellsize)
 | 
				
			||||||
 | 
								to_copy = src_gl->cellsize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Expand destination line. */
 | 
				
			||||||
 | 
							dst_gl->celldata = xmalloc(to_copy * sizeof *dst_gl->celldata);
 | 
				
			||||||
 | 
							dst_gl->cellsize = to_copy;
 | 
				
			||||||
 | 
							dst_gl->flags |= GRID_LINE_WRAPPED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Copy the data. */
 | 
				
			||||||
 | 
							memcpy (&dst_gl->celldata[0], &src_gl->celldata[offset],
 | 
				
			||||||
 | 
							    to_copy * sizeof dst_gl->celldata[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Move offset and reduce old line size. */
 | 
				
			||||||
 | 
							offset += to_copy;
 | 
				
			||||||
 | 
							src_gl->cellsize -= to_copy;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Last line is not wrapped. */
 | 
				
			||||||
 | 
						if (dst_gl != NULL)
 | 
				
			||||||
 | 
							dst_gl->flags &= ~GRID_LINE_WRAPPED;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Move line data. */
 | 
				
			||||||
 | 
					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);
 | 
				
			||||||
 | 
						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;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Reflow lines from src grid into dst grid based on width sx. Returns number
 | 
					 * Reflow lines from src grid into dst grid of width new_x. Returns number of
 | 
				
			||||||
 * of lines fewer in the visible area, or zero.
 | 
					 * lines fewer in the visible area. The source grid is destroyed.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
u_int
 | 
					u_int
 | 
				
			||||||
grid_reflow(struct grid *dst, const struct grid *src, u_int sx)
 | 
					grid_reflow(struct grid *dst, struct grid *src, u_int new_x)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u_int			 px, py, line, cell;
 | 
						u_int			 py, sy, line;
 | 
				
			||||||
	int			 previous_wrapped;
 | 
						int			 previous_wrapped;
 | 
				
			||||||
	struct grid_line	*gl;
 | 
						struct grid_line	*src_gl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	px = py = 0;
 | 
						py = 0;
 | 
				
			||||||
	previous_wrapped = 1;
 | 
						sy = src->sy;
 | 
				
			||||||
	for (line = 0; line < src->sy + src->hsize; line++) {
 | 
					
 | 
				
			||||||
		gl = src->linedata + line;
 | 
						previous_wrapped = 0;
 | 
				
			||||||
 | 
						for (line = 0; line < sy + src->hsize; line++) {
 | 
				
			||||||
 | 
							src_gl = src->linedata + line;
 | 
				
			||||||
		if (!previous_wrapped) {
 | 
							if (!previous_wrapped) {
 | 
				
			||||||
			px = 0;
 | 
								/* Wasn't wrapped. If smaller, move to destination. */
 | 
				
			||||||
			py++;
 | 
								if (src_gl->cellsize <= new_x)
 | 
				
			||||||
			if (py >= dst->hsize + dst->sy)
 | 
									grid_reflow_move(dst, &py, src_gl);
 | 
				
			||||||
				grid_scroll_history(dst);
 | 
								else
 | 
				
			||||||
 | 
									grid_reflow_split(dst, &py, src_gl, new_x, 0);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								/* Previous was wrapped. Try to join. */
 | 
				
			||||||
 | 
								grid_reflow_join(dst, &py, src_gl, new_x);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		for (cell = 0; cell < gl->cellsize; cell++) {
 | 
							previous_wrapped = src_gl->flags & GRID_LINE_WRAPPED;
 | 
				
			||||||
			if (px == sx) {
 | 
					 | 
				
			||||||
				dst->linedata[py].flags |= GRID_LINE_WRAPPED;
 | 
					 | 
				
			||||||
				px = 0;
 | 
					 | 
				
			||||||
				py++;
 | 
					 | 
				
			||||||
				if (py >= dst->hsize + dst->sy)
 | 
					 | 
				
			||||||
					grid_scroll_history(dst);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			grid_set_cell(dst, px, py, gl->celldata + cell);
 | 
					 | 
				
			||||||
			px++;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		previous_wrapped = gl->flags & GRID_LINE_WRAPPED;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	py++; /* account for final line, which never wraps */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (py > src->sy)
 | 
						grid_destroy(src);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (py > sy)
 | 
				
			||||||
		return (0);
 | 
							return (0);
 | 
				
			||||||
	return (src->sy - py);
 | 
						return (sy - py);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										13
									
								
								screen.c
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								screen.c
									
									
									
									
									
								
							@@ -362,15 +362,10 @@ screen_check_selection(struct screen *s, u_int px, u_int py)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Reflow wrapped lines. */
 | 
					/* Reflow wrapped lines. */
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
screen_reflow(struct screen *s, u_int sx)
 | 
					screen_reflow(struct screen *s, u_int new_x)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct grid	*old, *new;
 | 
						struct grid	*old = s->grid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	old = s->grid;
 | 
						s->grid = grid_create(old->sx, old->sy, old->hlimit);
 | 
				
			||||||
	new = grid_create(old->sx, old->sy, old->hlimit);
 | 
						s->cy -= grid_reflow(s->grid, old, new_x);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	s->cy -= grid_reflow(new, old, sx);
 | 
					 | 
				
			||||||
	s->grid = new;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	grid_destroy(old);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user