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); | ||||
|  | ||||
| static void	screen_resize_y(struct screen *, u_int); | ||||
|  | ||||
| static void	screen_reflow(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 *); | ||||
|  | ||||
| /* Free titles stack. */ | ||||
| static void | ||||
| @@ -216,10 +215,23 @@ screen_pop_title(struct screen *s) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| /* Resize screen. */ | ||||
| /* Resize screen and return cursor position. */ | ||||
| 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) | ||||
| 		sx = 1; | ||||
| 	if (sy < 1) | ||||
| @@ -232,14 +244,30 @@ screen_resize(struct screen *s, u_int sx, u_int sy, int reflow) | ||||
| 		reflow = 0; | ||||
|  | ||||
| 	if (sy != screen_size_y(s)) | ||||
| 		screen_resize_y(s, sy); | ||||
| 		screen_resize_y(s, sy, eat_empty); | ||||
|  | ||||
| 	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 | ||||
| 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; | ||||
| 	u_int		 needed, available, oldy, i; | ||||
| @@ -264,14 +292,16 @@ screen_resize_y(struct screen *s, u_int sy) | ||||
| 		needed = oldy - sy; | ||||
|  | ||||
| 		/* Delete as many lines as possible from the bottom. */ | ||||
| 		if (eat_empty) { | ||||
| 			available = oldy - 1 - s->cy; | ||||
| 			if (available > 0) { | ||||
| 				if (available > needed) | ||||
| 					available = needed; | ||||
| 			grid_view_delete_lines(gd, oldy - available, available, | ||||
| 			    8); | ||||
| 				grid_view_delete_lines(gd, oldy - available, | ||||
| 				    available, 8); | ||||
| 			} | ||||
| 			needed -= available; | ||||
| 		} | ||||
|  | ||||
| 		/* | ||||
| 		 * 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; | ||||
| 			grid_view_delete_lines(gd, 0, available, 8); | ||||
| 		} | ||||
| 		s->cy -= needed; | ||||
| 	} | ||||
|  | ||||
| 	/* Resize line array. */ | ||||
| @@ -307,7 +336,6 @@ screen_resize_y(struct screen *s, u_int sy) | ||||
| 				available = needed; | ||||
| 			gd->hscrolled -= available; | ||||
| 			gd->hsize -= available; | ||||
| 			s->cy += available; | ||||
| 		} else | ||||
| 			available = 0; | ||||
| 		needed -= available; | ||||
| @@ -482,25 +510,17 @@ screen_select_cell(struct screen *s, struct grid_cell *dst, | ||||
|  | ||||
| /* Reflow wrapped lines. */ | ||||
| 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); | ||||
| 	log_debug("%s: cursor %u,%u is %u,%u", __func__, 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); | ||||
|  | ||||
| 	grid_reflow(s->grid, new_x); | ||||
|  | ||||
| 	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) { | ||||
| 		s->cx = cx; | ||||
| 		s->cy = cy - s->grid->hsize; | ||||
| 	} else { | ||||
| 		s->cx = 0; | ||||
| 		s->cy = 0; | ||||
| 	} | ||||
| 	grid_unwrap_position(s->grid, cx, cy, wx, wy); | ||||
| 	log_debug("%s: new cursor is %u,%u", __func__, *cx,* cy); | ||||
| } | ||||
|  | ||||
| /* | ||||
|   | ||||
							
								
								
									
										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_pop_title(struct screen *); | ||||
| 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, | ||||
| 	     u_int, int, struct grid_cell *); | ||||
| 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 * | ||||
| 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_write_ctx		 ctx; | ||||
| 	u_int				 dy, sy; | ||||
| 	u_int			 sy; | ||||
| 	const struct grid_line	*gl; | ||||
|  | ||||
| 	dst = xcalloc(1, sizeof *dst); | ||||
|  | ||||
| 	sy = screen_hsize(src) + screen_size_y(src); | ||||
| 	if (screen_size_y(hint) > sy) | ||||
| 		dy = screen_size_y(hint); | ||||
| 	else | ||||
| 		dy = sy; | ||||
| 	screen_init(dst, screen_size_x(src), dy, src->grid->hlimit); | ||||
|  | ||||
| 	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); | ||||
| 	while (sy > screen_hsize(src)) { | ||||
| 		gl = grid_peek_line(src->grid, sy - 1); | ||||
| 		if (gl->cellused != 0) | ||||
| 			break; | ||||
| 		sy--; | ||||
| 	} | ||||
| 	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); | ||||
| 	screen_write_cursormove(&ctx, 0, dst->grid->sy + sy - dy - 1, 0); | ||||
| 	screen_write_stop(&ctx); | ||||
| 	dst->grid->sy = sy - screen_hsize(src); | ||||
| 	dst->grid->hsize = screen_hsize(src); | ||||
| 	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); | ||||
| } | ||||
| @@ -370,22 +373,22 @@ window_copy_init(struct window_mode_entry *wme, | ||||
| { | ||||
| 	struct window_pane		*wp = wme->swp; | ||||
| 	struct window_copy_mode_data	*data; | ||||
| 	struct screen			*base = &wp->base; | ||||
| 	struct screen_write_ctx		 ctx; | ||||
| 	u_int				 i; | ||||
| 	u_int				 i, cx, cy; | ||||
|  | ||||
| 	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 (data->cx > screen_size_x(&data->screen) - 1) | ||||
| 		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; | ||||
| 	if (cy < screen_hsize(data->backing)) { | ||||
| 		data->cx = cx; | ||||
| 		data->cy = 0; | ||||
| 	} else | ||||
| 		data->cy -= screen_hsize(data->backing); | ||||
| 		data->oy = screen_hsize(data->backing) - cy; | ||||
| 	} else { | ||||
| 		data->cx = data->backing->cx; | ||||
| 		data->cy = data->backing->cy; | ||||
| 		data->oy = 0; | ||||
| 	} | ||||
|  | ||||
| 	data->scroll_exit = args_has(args, 'e'); | ||||
| 	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; | ||||
| 	int				 search; | ||||
|  | ||||
| 	screen_resize(s, sx, sy, 1); | ||||
| 	screen_resize(data->backing, sx, sy, 1); | ||||
| 	screen_resize(s, sx, sy, 0); | ||||
| 	screen_resize_cursor(data->backing, sx, sy, 1, 0, NULL, NULL); | ||||
|  | ||||
| 	if (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); | ||||
| 	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); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 nicm
					nicm