mirror of
				https://github.com/tmux/tmux.git
				synced 2025-10-26 12:27:15 +00:00 
			
		
		
		
	Instead of fixing with the cursor position when the copied screen is
created, resize it and let the resize/reflow code fix it up and return it. Solves various problems with cursor position and resizing when in copy mode. With Anindya Mukherjee.
This commit is contained in:
		
							
								
								
									
										72
									
								
								screen.c
									
									
									
									
									
								
							
							
						
						
									
										72
									
								
								screen.c
									
									
									
									
									
								
							| @@ -48,9 +48,8 @@ struct screen_title_entry { | |||||||
| }; | }; | ||||||
| TAILQ_HEAD(screen_titles, screen_title_entry); | TAILQ_HEAD(screen_titles, screen_title_entry); | ||||||
|  |  | ||||||
| static void	screen_resize_y(struct screen *, u_int); | static void	screen_resize_y(struct screen *, u_int, int); | ||||||
|  | static void	screen_reflow(struct screen *, u_int, u_int *, u_int *); | ||||||
| static void	screen_reflow(struct screen *, u_int); |  | ||||||
|  |  | ||||||
| /* Free titles stack. */ | /* Free titles stack. */ | ||||||
| static void | static void | ||||||
| @@ -216,10 +215,23 @@ screen_pop_title(struct screen *s) | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| /* Resize screen. */ | /* Resize screen and return cursor position. */ | ||||||
| void | void | ||||||
| screen_resize(struct screen *s, u_int sx, u_int sy, int reflow) | screen_resize_cursor(struct screen *s, u_int sx, u_int sy, int reflow, | ||||||
|  |     int eat_empty, u_int *cx, u_int *cy) | ||||||
| { | { | ||||||
|  | 	u_int	tcx, tcy; | ||||||
|  |  | ||||||
|  | 	if (cx == NULL) | ||||||
|  | 		cx = &tcx; | ||||||
|  | 	*cx = s->cx; | ||||||
|  |  | ||||||
|  | 	if (cy == NULL) | ||||||
|  | 		cy = т | ||||||
|  | 	*cy = s->grid->hsize + s->cy; | ||||||
|  |  | ||||||
|  | 	log_debug("%s: start %u,%u (%u,%u)", __func__, s->cx, s->cy, *cx, *cy); | ||||||
|  |  | ||||||
| 	if (sx < 1) | 	if (sx < 1) | ||||||
| 		sx = 1; | 		sx = 1; | ||||||
| 	if (sy < 1) | 	if (sy < 1) | ||||||
| @@ -232,14 +244,30 @@ screen_resize(struct screen *s, u_int sx, u_int sy, int reflow) | |||||||
| 		reflow = 0; | 		reflow = 0; | ||||||
|  |  | ||||||
| 	if (sy != screen_size_y(s)) | 	if (sy != screen_size_y(s)) | ||||||
| 		screen_resize_y(s, sy); | 		screen_resize_y(s, sy, eat_empty); | ||||||
|  |  | ||||||
| 	if (reflow) | 	if (reflow) | ||||||
| 		screen_reflow(s, sx); | 		screen_reflow(s, sx, cx, cy); | ||||||
|  |  | ||||||
|  | 	if (*cy >= s->grid->hsize) { | ||||||
|  | 		s->cx = *cx; | ||||||
|  | 		s->cy = (*cy) - s->grid->hsize; | ||||||
|  | 	} else { | ||||||
|  | 		s->cx = 0; | ||||||
|  | 		s->cy = 0; | ||||||
|  | 	} | ||||||
|  | 	log_debug("%s: finish %u,%u (%u,%u)", __func__, s->cx, s->cy, *cx, *cy); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Resize screen. */ | ||||||
|  | void | ||||||
|  | screen_resize(struct screen *s, u_int sx, u_int sy, int reflow) | ||||||
|  | { | ||||||
|  | 	screen_resize_cursor(s, sx, sy, reflow, 1, NULL, NULL); | ||||||
| } | } | ||||||
|  |  | ||||||
| static void | static void | ||||||
| screen_resize_y(struct screen *s, u_int sy) | screen_resize_y(struct screen *s, u_int sy, int eat_empty) | ||||||
| { | { | ||||||
| 	struct grid	*gd = s->grid; | 	struct grid	*gd = s->grid; | ||||||
| 	u_int		 needed, available, oldy, i; | 	u_int		 needed, available, oldy, i; | ||||||
| @@ -264,14 +292,16 @@ screen_resize_y(struct screen *s, u_int sy) | |||||||
| 		needed = oldy - sy; | 		needed = oldy - sy; | ||||||
|  |  | ||||||
| 		/* Delete as many lines as possible from the bottom. */ | 		/* Delete as many lines as possible from the bottom. */ | ||||||
|  | 		if (eat_empty) { | ||||||
| 			available = oldy - 1 - s->cy; | 			available = oldy - 1 - s->cy; | ||||||
| 			if (available > 0) { | 			if (available > 0) { | ||||||
| 				if (available > needed) | 				if (available > needed) | ||||||
| 					available = needed; | 					available = needed; | ||||||
| 			grid_view_delete_lines(gd, oldy - available, available, | 				grid_view_delete_lines(gd, oldy - available, | ||||||
| 			    8); | 				    available, 8); | ||||||
| 			} | 			} | ||||||
| 			needed -= available; | 			needed -= available; | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		/* | 		/* | ||||||
| 		 * Now just increase the history size, if possible, to take | 		 * Now just increase the history size, if possible, to take | ||||||
| @@ -287,7 +317,6 @@ screen_resize_y(struct screen *s, u_int sy) | |||||||
| 				available = needed; | 				available = needed; | ||||||
| 			grid_view_delete_lines(gd, 0, available, 8); | 			grid_view_delete_lines(gd, 0, available, 8); | ||||||
| 		} | 		} | ||||||
| 		s->cy -= needed; |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	/* Resize line array. */ | 	/* Resize line array. */ | ||||||
| @@ -307,7 +336,6 @@ screen_resize_y(struct screen *s, u_int sy) | |||||||
| 				available = needed; | 				available = needed; | ||||||
| 			gd->hscrolled -= available; | 			gd->hscrolled -= available; | ||||||
| 			gd->hsize -= available; | 			gd->hsize -= available; | ||||||
| 			s->cy += available; |  | ||||||
| 		} else | 		} else | ||||||
| 			available = 0; | 			available = 0; | ||||||
| 		needed -= available; | 		needed -= available; | ||||||
| @@ -482,25 +510,17 @@ screen_select_cell(struct screen *s, struct grid_cell *dst, | |||||||
|  |  | ||||||
| /* Reflow wrapped lines. */ | /* Reflow wrapped lines. */ | ||||||
| static void | static void | ||||||
| screen_reflow(struct screen *s, u_int new_x) | screen_reflow(struct screen *s, u_int new_x, u_int *cx, u_int *cy) | ||||||
| { | { | ||||||
| 	u_int	cx = s->cx, cy = s->grid->hsize + s->cy, wx, wy; | 	u_int	wx, wy; | ||||||
|  |  | ||||||
| 	grid_wrap_position(s->grid, cx, cy, &wx, &wy); | 	grid_wrap_position(s->grid, *cx, *cy, &wx, &wy); | ||||||
| 	log_debug("%s: cursor %u,%u is %u,%u", __func__, 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_reflow(s->grid, new_x); | ||||||
|  |  | ||||||
| 	grid_unwrap_position(s->grid, &cx, &cy, wx, wy); | 	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) { |  | ||||||
| 		s->cx = cx; |  | ||||||
| 		s->cy = cy - s->grid->hsize; |  | ||||||
| 	} else { |  | ||||||
| 		s->cx = 0; |  | ||||||
| 		s->cy = 0; |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | /* | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								tmux.h
									
									
									
									
									
								
							| @@ -2437,6 +2437,8 @@ void	 screen_set_path(struct screen *, const char *); | |||||||
| void	 screen_push_title(struct screen *); | void	 screen_push_title(struct screen *); | ||||||
| void	 screen_pop_title(struct screen *); | void	 screen_pop_title(struct screen *); | ||||||
| void	 screen_resize(struct screen *, u_int, u_int, int); | void	 screen_resize(struct screen *, u_int, u_int, int); | ||||||
|  | void	 screen_resize_cursor(struct screen *, u_int, u_int, int, int, u_int *, | ||||||
|  | 	     u_int *); | ||||||
| void	 screen_set_selection(struct screen *, u_int, u_int, u_int, u_int, | void	 screen_set_selection(struct screen *, u_int, u_int, u_int, u_int, | ||||||
| 	     u_int, int, struct grid_cell *); | 	     u_int, int, struct grid_cell *); | ||||||
| void	 screen_clear_selection(struct screen *); | void	 screen_clear_selection(struct screen *); | ||||||
|   | |||||||
| @@ -298,30 +298,33 @@ window_copy_scroll_timer(__unused int fd, __unused short events, void *arg) | |||||||
| } | } | ||||||
|  |  | ||||||
| static struct screen * | static struct screen * | ||||||
| window_copy_clone_screen(struct screen *src, struct screen *hint) | window_copy_clone_screen(struct screen *src, struct screen *hint, u_int *cx, | ||||||
|  |     u_int *cy) | ||||||
| { | { | ||||||
| 	struct screen		*dst; | 	struct screen		*dst; | ||||||
| 	struct screen_write_ctx		 ctx; | 	u_int			 sy; | ||||||
| 	u_int				 dy, sy; | 	const struct grid_line	*gl; | ||||||
|  |  | ||||||
| 	dst = xcalloc(1, sizeof *dst); | 	dst = xcalloc(1, sizeof *dst); | ||||||
|  |  | ||||||
| 	sy = screen_hsize(src) + screen_size_y(src); | 	sy = screen_hsize(src) + screen_size_y(src); | ||||||
| 	if (screen_size_y(hint) > sy) | 	while (sy > screen_hsize(src)) { | ||||||
| 		dy = screen_size_y(hint); | 		gl = grid_peek_line(src->grid, sy - 1); | ||||||
| 	else | 		if (gl->cellused != 0) | ||||||
| 		dy = sy; | 			break; | ||||||
| 	screen_init(dst, screen_size_x(src), dy, src->grid->hlimit); | 		sy--; | ||||||
|  |  | ||||||
| 	grid_duplicate_lines(dst->grid, 0, src->grid, 0, sy); |  | ||||||
| 	if (screen_size_y(hint) < sy) { |  | ||||||
| 		dst->grid->sy = screen_size_y(hint); |  | ||||||
| 		dst->grid->hsize = sy - screen_size_y(hint); |  | ||||||
| 	} | 	} | ||||||
|  | 	screen_init(dst, screen_size_x(src), sy, screen_hlimit(src)); | ||||||
|  | 	grid_duplicate_lines(dst->grid, 0, src->grid, 0, sy); | ||||||
|  |  | ||||||
| 	screen_write_start(&ctx, NULL, dst); | 	dst->grid->sy = sy - screen_hsize(src); | ||||||
| 	screen_write_cursormove(&ctx, 0, dst->grid->sy + sy - dy - 1, 0); | 	dst->grid->hsize = screen_hsize(src); | ||||||
| 	screen_write_stop(&ctx); | 	dst->grid->hscrolled = src->grid->hscrolled; | ||||||
|  | 	dst->cx = src->cx; | ||||||
|  | 	dst->cy = src->cy; | ||||||
|  |  | ||||||
|  | 	screen_resize_cursor(dst, screen_size_x(hint), screen_size_y(hint), 1, | ||||||
|  | 	    0, cx, cy); | ||||||
|  |  | ||||||
| 	return (dst); | 	return (dst); | ||||||
| } | } | ||||||
| @@ -370,22 +373,22 @@ window_copy_init(struct window_mode_entry *wme, | |||||||
| { | { | ||||||
| 	struct window_pane		*wp = wme->swp; | 	struct window_pane		*wp = wme->swp; | ||||||
| 	struct window_copy_mode_data	*data; | 	struct window_copy_mode_data	*data; | ||||||
|  | 	struct screen			*base = &wp->base; | ||||||
| 	struct screen_write_ctx		 ctx; | 	struct screen_write_ctx		 ctx; | ||||||
| 	u_int				 i; | 	u_int				 i, cx, cy; | ||||||
|  |  | ||||||
| 	data = window_copy_common_init(wme); | 	data = window_copy_common_init(wme); | ||||||
| 	data->backing = window_copy_clone_screen(&wp->base, &data->screen); | 	data->backing = window_copy_clone_screen(base, &data->screen, &cx, &cy); | ||||||
|  |  | ||||||
| 	data->cx = wp->base.cx; | 	if (cy < screen_hsize(data->backing)) { | ||||||
| 	if (data->cx > screen_size_x(&data->screen) - 1) | 		data->cx = cx; | ||||||
| 		data->cx = screen_size_x(&data->screen) - 1; |  | ||||||
|  |  | ||||||
| 	data->cy = screen_hsize(&wp->base) + wp->base.cy; |  | ||||||
| 	if (data->cy < screen_hsize(data->backing)) { |  | ||||||
| 		data->oy = screen_hsize(data->backing) - data->cy; |  | ||||||
| 		data->cy = 0; | 		data->cy = 0; | ||||||
| 	} else | 		data->oy = screen_hsize(data->backing) - cy; | ||||||
| 		data->cy -= screen_hsize(data->backing); | 	} else { | ||||||
|  | 		data->cx = data->backing->cx; | ||||||
|  | 		data->cy = data->backing->cy; | ||||||
|  | 		data->oy = 0; | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	data->scroll_exit = args_has(args, 'e'); | 	data->scroll_exit = args_has(args, 'e'); | ||||||
| 	data->hide_position = args_has(args, 'H'); | 	data->hide_position = args_has(args, 'H'); | ||||||
| @@ -697,8 +700,8 @@ window_copy_resize(struct window_mode_entry *wme, u_int sx, u_int sy) | |||||||
| 	struct screen_write_ctx	 	 ctx; | 	struct screen_write_ctx	 	 ctx; | ||||||
| 	int				 search; | 	int				 search; | ||||||
|  |  | ||||||
| 	screen_resize(s, sx, sy, 1); | 	screen_resize(s, sx, sy, 0); | ||||||
| 	screen_resize(data->backing, sx, sy, 1); | 	screen_resize_cursor(data->backing, sx, sy, 1, 0, NULL, NULL); | ||||||
|  |  | ||||||
| 	if (data->cy > sy - 1) | 	if (data->cy > sy - 1) | ||||||
| 		data->cy = sy - 1; | 		data->cy = sy - 1; | ||||||
| @@ -2024,7 +2027,8 @@ window_copy_cmd_refresh_from_pane(struct window_copy_cmd_state *cs) | |||||||
|  |  | ||||||
| 	screen_free(data->backing); | 	screen_free(data->backing); | ||||||
| 	free(data->backing); | 	free(data->backing); | ||||||
| 	data->backing = window_copy_clone_screen(&wp->base, &data->screen); | 	data->backing = window_copy_clone_screen(&wp->base, &data->screen, NULL, | ||||||
|  | 	    NULL); | ||||||
|  |  | ||||||
| 	return (WINDOW_COPY_CMD_REDRAW); | 	return (WINDOW_COPY_CMD_REDRAW); | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 nicm
					nicm