mirror of
				https://github.com/tmux/tmux.git
				synced 2025-10-26 12:27:15 +00:00 
			
		
		
		
	Instead of overloading the line clear function to mean free if
background is default (8), introduce an explicit free function and use it where a free alone is needed. Likewise, use memmove directly rather than grid_move_lines where it makes sense. Based on a memory leak fix by Dan Aloni in GitHub issue 1051.
This commit is contained in:
		| @@ -75,7 +75,7 @@ grid_view_clear_history(struct grid *gd, u_int bg) | |||||||
|  |  | ||||||
| 	/* Scroll the lines into the history. */ | 	/* Scroll the lines into the history. */ | ||||||
| 	for (yy = 0; yy < last; yy++) { | 	for (yy = 0; yy < last; yy++) { | ||||||
| 		grid_collect_history(gd, bg); | 		grid_collect_history(gd); | ||||||
| 		grid_scroll_history(gd, bg); | 		grid_scroll_history(gd, bg); | ||||||
| 	} | 	} | ||||||
| 	if (last < gd->sy) | 	if (last < gd->sy) | ||||||
| @@ -100,7 +100,7 @@ grid_view_scroll_region_up(struct grid *gd, u_int rupper, u_int rlower, | |||||||
|     u_int bg) |     u_int bg) | ||||||
| { | { | ||||||
| 	if (gd->flags & GRID_HISTORY) { | 	if (gd->flags & GRID_HISTORY) { | ||||||
| 		grid_collect_history(gd, bg); | 		grid_collect_history(gd); | ||||||
| 		if (rupper == 0 && rlower == gd->sy - 1) | 		if (rupper == 0 && rlower == gd->sy - 1) | ||||||
| 			grid_scroll_history(gd, bg); | 			grid_scroll_history(gd, bg); | ||||||
| 		else { | 		else { | ||||||
|   | |||||||
							
								
								
									
										74
									
								
								grid.c
									
									
									
									
									
								
							
							
						
						
									
										74
									
								
								grid.c
									
									
									
									
									
								
							| @@ -162,6 +162,26 @@ grid_cells_equal(const struct grid_cell *gca, const struct grid_cell *gcb) | |||||||
| 	return (memcmp(gca->data.data, gcb->data.data, gca->data.size) == 0); | 	return (memcmp(gca->data.data, gcb->data.data, gca->data.size) == 0); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /* Free one line. */ | ||||||
|  | static void | ||||||
|  | grid_free_line(struct grid *gd, u_int py) | ||||||
|  | { | ||||||
|  | 	free(gd->linedata[py].celldata); | ||||||
|  | 	gd->linedata[py].celldata = NULL; | ||||||
|  | 	free(gd->linedata[py].extddata); | ||||||
|  | 	gd->linedata[py].extddata = NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Free several lines. */ | ||||||
|  | static void | ||||||
|  | grid_free_lines(struct grid *gd, u_int py, u_int ny) | ||||||
|  | { | ||||||
|  | 	u_int	yy; | ||||||
|  |  | ||||||
|  | 	for (yy = py; yy < py + ny; yy++) | ||||||
|  | 		grid_free_line(gd, yy); | ||||||
|  | } | ||||||
|  |  | ||||||
| /* 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) | ||||||
| @@ -187,14 +207,7 @@ grid_create(u_int sx, u_int sy, u_int hlimit) | |||||||
| void | void | ||||||
| grid_destroy(struct grid *gd) | grid_destroy(struct grid *gd) | ||||||
| { | { | ||||||
| 	struct grid_line	*gl; | 	grid_free_lines(gd, 0, gd->hsize + gd->sy); | ||||||
| 	u_int			 yy; |  | ||||||
|  |  | ||||||
| 	for (yy = 0; yy < gd->hsize + gd->sy; yy++) { |  | ||||||
| 		gl = &gd->linedata[yy]; |  | ||||||
| 		free(gl->celldata); |  | ||||||
| 		free(gl->extddata); |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	free(gd->linedata); | 	free(gd->linedata); | ||||||
|  |  | ||||||
| @@ -233,19 +246,26 @@ grid_compare(struct grid *ga, struct grid *gb) | |||||||
|  * and shift up. |  * and shift up. | ||||||
|  */ |  */ | ||||||
| void | void | ||||||
| grid_collect_history(struct grid *gd, u_int bg) | grid_collect_history(struct grid *gd) | ||||||
| { | { | ||||||
| 	u_int	yy; | 	u_int	ny; | ||||||
|  |  | ||||||
| 	if (gd->hsize < gd->hlimit) | 	if (gd->hsize < gd->hlimit) | ||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	yy = gd->hlimit / 10; | 	ny = gd->hlimit / 10; | ||||||
| 	if (yy < 1) | 	if (ny < 1) | ||||||
| 		yy = 1; | 		ny = 1; | ||||||
|  |  | ||||||
| 	grid_move_lines(gd, 0, yy, gd->hsize + gd->sy - yy, bg); | 	/* | ||||||
| 	gd->hsize -= yy; | 	 * Free the lines from 0 to ny then move the remaining lines over | ||||||
|  | 	 * them. | ||||||
|  | 	 */ | ||||||
|  | 	grid_free_lines(gd, 0, ny); | ||||||
|  | 	memmove(&gd->linedata[0], &gd->linedata[ny], | ||||||
|  | 	    (gd->hsize + gd->sy - ny) * (sizeof *gd->linedata)); | ||||||
|  |  | ||||||
|  | 	gd->hsize -= ny; | ||||||
| 	if (gd->hscrolled > gd->hsize) | 	if (gd->hscrolled > gd->hsize) | ||||||
| 		gd->hscrolled = gd->hsize; | 		gd->hscrolled = gd->hsize; | ||||||
| } | } | ||||||
| @@ -272,8 +292,9 @@ grid_scroll_history(struct grid *gd, u_int bg) | |||||||
| void | void | ||||||
| grid_clear_history(struct grid *gd) | grid_clear_history(struct grid *gd) | ||||||
| { | { | ||||||
| 	grid_clear_lines(gd, 0, gd->hsize, 8); | 	grid_free_lines(gd, 0, gd->hsize); | ||||||
| 	grid_move_lines(gd, 0, gd->hsize, gd->sy, 8); | 	memmove(&gd->linedata[0], &gd->linedata[gd->hsize], | ||||||
|  | 	    gd->sy * (sizeof *gd->linedata)); | ||||||
|  |  | ||||||
| 	gd->hscrolled = 0; | 	gd->hscrolled = 0; | ||||||
| 	gd->hsize = 0; | 	gd->hsize = 0; | ||||||
| @@ -481,7 +502,6 @@ grid_clear(struct grid *gd, u_int px, u_int py, u_int nx, u_int ny, u_int bg) | |||||||
| void | void | ||||||
| grid_clear_lines(struct grid *gd, u_int py, u_int ny, u_int bg) | grid_clear_lines(struct grid *gd, u_int py, u_int ny, u_int bg) | ||||||
| { | { | ||||||
| 	struct grid_line	*gl; |  | ||||||
| 	u_int	yy; | 	u_int	yy; | ||||||
|  |  | ||||||
| 	if (ny == 0) | 	if (ny == 0) | ||||||
| @@ -493,9 +513,7 @@ grid_clear_lines(struct grid *gd, u_int py, u_int ny, u_int bg) | |||||||
| 		return; | 		return; | ||||||
|  |  | ||||||
| 	for (yy = py; yy < py + ny; yy++) { | 	for (yy = py; yy < py + ny; yy++) { | ||||||
| 		gl = &gd->linedata[yy]; | 		grid_free_line(gd, yy); | ||||||
| 		free(gl->celldata); |  | ||||||
| 		free(gl->extddata); |  | ||||||
| 		grid_empty_line(gd, yy, bg); | 		grid_empty_line(gd, yy, bg); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -522,13 +540,16 @@ grid_move_lines(struct grid *gd, u_int dy, u_int py, u_int ny, u_int bg) | |||||||
| 	for (yy = dy; yy < dy + ny; yy++) { | 	for (yy = dy; yy < dy + ny; yy++) { | ||||||
| 		if (yy >= py && yy < py + ny) | 		if (yy >= py && yy < py + ny) | ||||||
| 			continue; | 			continue; | ||||||
| 		grid_clear_lines(gd, yy, 1, bg); | 		grid_free_line(gd, yy); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	memmove(&gd->linedata[dy], &gd->linedata[py], | 	memmove(&gd->linedata[dy], &gd->linedata[py], | ||||||
| 	    ny * (sizeof *gd->linedata)); | 	    ny * (sizeof *gd->linedata)); | ||||||
|  |  | ||||||
| 	/* Wipe any lines that have been moved (without freeing them). */ | 	/* | ||||||
|  | 	 * Wipe any lines that have been moved (without freeing them - they are | ||||||
|  | 	 * still present). | ||||||
|  | 	 */ | ||||||
| 	for (yy = py; yy < py + ny; yy++) { | 	for (yy = py; yy < py + ny; yy++) { | ||||||
| 		if (yy < dy || yy >= dy + ny) | 		if (yy < dy || yy >= dy + ny) | ||||||
| 			grid_empty_line(gd, yy, bg); | 			grid_empty_line(gd, yy, bg); | ||||||
| @@ -845,9 +866,8 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx, | |||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * Duplicate a set of lines between two grids. If there aren't enough lines in |  * Duplicate a set of lines between two grids. Both source and destination | ||||||
|  * either source or destination, the number of lines is limited to the number |  * should be big enough. | ||||||
|  * available. |  | ||||||
|  */ |  */ | ||||||
| void | void | ||||||
| grid_duplicate_lines(struct grid *dst, u_int dy, struct grid *src, u_int sy, | grid_duplicate_lines(struct grid *dst, u_int dy, struct grid *src, u_int sy, | ||||||
| @@ -860,7 +880,7 @@ grid_duplicate_lines(struct grid *dst, u_int dy, struct grid *src, u_int sy, | |||||||
| 		ny = dst->hsize + dst->sy - dy; | 		ny = dst->hsize + dst->sy - dy; | ||||||
| 	if (sy + ny > src->hsize + src->sy) | 	if (sy + ny > src->hsize + src->sy) | ||||||
| 		ny = src->hsize + src->sy - sy; | 		ny = src->hsize + src->sy - sy; | ||||||
| 	grid_clear_lines(dst, dy, ny, 8); | 	grid_free_lines(dst, dy, ny); | ||||||
|  |  | ||||||
| 	for (yy = 0; yy < ny; yy++) { | 	for (yy = 0; yy < ny; yy++) { | ||||||
| 		srcl = &src->linedata[sy]; | 		srcl = &src->linedata[sy]; | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								tmux.h
									
									
									
									
									
								
							| @@ -1973,7 +1973,7 @@ int	 grid_cells_equal(const struct grid_cell *, const struct grid_cell *); | |||||||
| struct grid *grid_create(u_int, u_int, u_int); | struct grid *grid_create(u_int, u_int, u_int); | ||||||
| void	 grid_destroy(struct grid *); | void	 grid_destroy(struct grid *); | ||||||
| int	 grid_compare(struct grid *, struct grid *); | int	 grid_compare(struct grid *, struct grid *); | ||||||
| void	 grid_collect_history(struct grid *, u_int); | void	 grid_collect_history(struct grid *); | ||||||
| void	 grid_scroll_history(struct grid *, u_int); | void	 grid_scroll_history(struct grid *, u_int); | ||||||
| void	 grid_scroll_history_region(struct grid *, u_int, u_int, u_int); | void	 grid_scroll_history_region(struct grid *, u_int, u_int, u_int); | ||||||
| void	 grid_clear_history(struct grid *); | void	 grid_clear_history(struct grid *); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 nicm
					nicm