mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Rectangle copy support, from Robin Lee Powell.
This commit is contained in:
		@@ -89,6 +89,7 @@ struct mode_key_cmdstr mode_key_cmdstr_copy[] = {
 | 
				
			|||||||
	{ MODEKEYCOPY_HISTORYBOTTOM, "history-bottom" },
 | 
						{ MODEKEYCOPY_HISTORYBOTTOM, "history-bottom" },
 | 
				
			||||||
	{ MODEKEYCOPY_HISTORYTOP, "history-top" },
 | 
						{ MODEKEYCOPY_HISTORYTOP, "history-top" },
 | 
				
			||||||
	{ MODEKEYCOPY_LEFT, "cursor-left" },
 | 
						{ MODEKEYCOPY_LEFT, "cursor-left" },
 | 
				
			||||||
 | 
						{ MODEKEYCOPY_RECTANGLETOGGLE, "rectangle-toggle" },
 | 
				
			||||||
	{ MODEKEYCOPY_MIDDLELINE, "middle-line" },
 | 
						{ MODEKEYCOPY_MIDDLELINE, "middle-line" },
 | 
				
			||||||
	{ MODEKEYCOPY_NEXTPAGE, "page-down" },
 | 
						{ MODEKEYCOPY_NEXTPAGE, "page-down" },
 | 
				
			||||||
	{ MODEKEYCOPY_NEXTSPACE, "next-space" },
 | 
						{ MODEKEYCOPY_NEXTSPACE, "next-space" },
 | 
				
			||||||
@@ -207,6 +208,7 @@ const struct mode_key_entry mode_key_vi_copy[] = {
 | 
				
			|||||||
	{ 'l',			0, MODEKEYCOPY_RIGHT },
 | 
						{ 'l',			0, MODEKEYCOPY_RIGHT },
 | 
				
			||||||
	{ 'n',			0, MODEKEYCOPY_SEARCHAGAIN },
 | 
						{ 'n',			0, MODEKEYCOPY_SEARCHAGAIN },
 | 
				
			||||||
	{ 'q',			0, MODEKEYCOPY_CANCEL },
 | 
						{ 'q',			0, MODEKEYCOPY_CANCEL },
 | 
				
			||||||
 | 
						{ 'v',			0, MODEKEYCOPY_RECTANGLETOGGLE },
 | 
				
			||||||
	{ 'w',			0, MODEKEYCOPY_NEXTWORD },
 | 
						{ 'w',			0, MODEKEYCOPY_NEXTWORD },
 | 
				
			||||||
	{ KEYC_BSPACE,		0, MODEKEYCOPY_LEFT },
 | 
						{ KEYC_BSPACE,		0, MODEKEYCOPY_LEFT },
 | 
				
			||||||
	{ KEYC_DOWN | KEYC_CTRL,0, MODEKEYCOPY_SCROLLDOWN },
 | 
						{ KEYC_DOWN | KEYC_CTRL,0, MODEKEYCOPY_SCROLLDOWN },
 | 
				
			||||||
@@ -276,9 +278,10 @@ struct mode_key_tree mode_key_tree_emacs_choice;
 | 
				
			|||||||
/* emacs copy mode keys. */
 | 
					/* emacs copy mode keys. */
 | 
				
			||||||
const struct mode_key_entry mode_key_emacs_copy[] = {
 | 
					const struct mode_key_entry mode_key_emacs_copy[] = {
 | 
				
			||||||
	{ ' ',			0, MODEKEYCOPY_NEXTPAGE },
 | 
						{ ' ',			0, MODEKEYCOPY_NEXTPAGE },
 | 
				
			||||||
	{ '<' | KEYC_ESCAPE,0, MODEKEYCOPY_HISTORYTOP },
 | 
						{ '<' | KEYC_ESCAPE,    0, MODEKEYCOPY_HISTORYTOP },
 | 
				
			||||||
	{ '>' | KEYC_ESCAPE, 0, MODEKEYCOPY_HISTORYBOTTOM },
 | 
						{ '>' | KEYC_ESCAPE,    0, MODEKEYCOPY_HISTORYBOTTOM },
 | 
				
			||||||
	{ 'R' | KEYC_ESCAPE,	0, MODEKEYCOPY_TOPLINE },
 | 
						{ 'R' | KEYC_ESCAPE,	0, MODEKEYCOPY_TOPLINE },
 | 
				
			||||||
 | 
						{ 'R',			0, MODEKEYCOPY_RECTANGLETOGGLE },
 | 
				
			||||||
	{ '\000' /* C-Space */,	0, MODEKEYCOPY_STARTSELECTION },
 | 
						{ '\000' /* C-Space */,	0, MODEKEYCOPY_STARTSELECTION },
 | 
				
			||||||
	{ '\001' /* C-a */,	0, MODEKEYCOPY_STARTOFLINE },
 | 
						{ '\001' /* C-a */,	0, MODEKEYCOPY_STARTOFLINE },
 | 
				
			||||||
	{ '\002' /* C-b */,	0, MODEKEYCOPY_LEFT },
 | 
						{ '\002' /* C-b */,	0, MODEKEYCOPY_LEFT },
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										113
									
								
								screen.c
									
									
									
									
									
								
							
							
						
						
									
										113
									
								
								screen.c
									
									
									
									
									
								
							@@ -228,41 +228,17 @@ screen_resize_y(struct screen *s, u_int sy)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* Set selection. */
 | 
					/* Set selection. */
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
screen_set_selection(struct screen *s,
 | 
					screen_set_selection(struct screen *s, u_int sx, u_int sy,
 | 
				
			||||||
    u_int sx, u_int sy, u_int ex, u_int ey, struct grid_cell *gc)
 | 
					    u_int ex, u_int ey, u_int rectflag, struct grid_cell *gc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct screen_sel	*sel = &s->sel;
 | 
						struct screen_sel	*sel = &s->sel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memcpy(&sel->cell, gc, sizeof sel->cell);
 | 
						memcpy(&sel->cell, gc, sizeof sel->cell);
 | 
				
			||||||
	sel->flag = 1;
 | 
						sel->flag = 1;
 | 
				
			||||||
 | 
						sel->rectflag = rectflag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* starting line < ending line -- downward selection. */
 | 
						sel->sx = sx; sel->sy = sy;
 | 
				
			||||||
	if (sy < ey) {
 | 
						sel->ex = ex; sel->ey = ey;
 | 
				
			||||||
		sel->sx = sx; sel->sy = sy;
 | 
					 | 
				
			||||||
		sel->ex = ex; sel->ey = ey;
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* starting line > ending line -- upward selection. */
 | 
					 | 
				
			||||||
	if (sy > ey) {
 | 
					 | 
				
			||||||
		if (sx > 0) {
 | 
					 | 
				
			||||||
			sel->sx = ex; sel->sy = ey;
 | 
					 | 
				
			||||||
			sel->ex = sx - 1; sel->ey = sy;
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			sel->sx = ex; sel->sy = ey;
 | 
					 | 
				
			||||||
			sel->ex = -1; sel->ey = sy - 1;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* starting line == ending line. */
 | 
					 | 
				
			||||||
	if (ex < sx) {
 | 
					 | 
				
			||||||
		sel->sx = ex; sel->sy = ey;
 | 
					 | 
				
			||||||
		sel->ex = sx - 1; sel->ey = sy;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		sel->sx = sx; sel->sy = sy;
 | 
					 | 
				
			||||||
		sel->ex = ex; sel->ey = ey;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Clear selection. */
 | 
					/* Clear selection. */
 | 
				
			||||||
@@ -280,16 +256,81 @@ screen_check_selection(struct screen *s, u_int px, u_int py)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	struct screen_sel	*sel = &s->sel;
 | 
						struct screen_sel	*sel = &s->sel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!sel->flag || py < sel->sy || py > sel->ey)
 | 
						if (!sel->flag)
 | 
				
			||||||
		return (0);
 | 
							return (0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (py == sel->sy && py == sel->ey) {
 | 
						if (sel->rectflag) {
 | 
				
			||||||
		if (px < sel->sx || px > sel->ex)
 | 
							if (sel->sy < sel->ey) {
 | 
				
			||||||
			return (0);
 | 
								/* start line < end line -- downward selection. */
 | 
				
			||||||
		return (1);
 | 
								if (py < sel->sy || py > sel->ey)
 | 
				
			||||||
 | 
									return (0);
 | 
				
			||||||
 | 
							} else if (sel->sy > sel->ey) {
 | 
				
			||||||
 | 
								/* start line > end line -- upward selection. */
 | 
				
			||||||
 | 
								if (py > sel->sy || py < sel->ey)
 | 
				
			||||||
 | 
									return (0);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								/* starting line == ending line. */
 | 
				
			||||||
 | 
								if (py != sel->sy)
 | 
				
			||||||
 | 
									return (0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Need to include the selection start row, but not the cursor
 | 
				
			||||||
 | 
							 * row, which means the selection changes depending on which
 | 
				
			||||||
 | 
							 * one is on the left.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (sel->ex < sel->sx) {
 | 
				
			||||||
 | 
								/* Cursor (ex) is on the left. */
 | 
				
			||||||
 | 
								if (px <= sel->ex)
 | 
				
			||||||
 | 
									return (0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (px > sel->sx)
 | 
				
			||||||
 | 
									return (0);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								/* Selection start (sx) is on the left. */
 | 
				
			||||||
 | 
								if (px < sel->sx)
 | 
				
			||||||
 | 
									return (0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (px >= sel->ex)
 | 
				
			||||||
 | 
									return (0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Like emacs, keep the top-left-most character, and drop the
 | 
				
			||||||
 | 
							 * bottom-right-most, regardless of copy direction.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (sel->sy < sel->ey) {
 | 
				
			||||||
 | 
								/* starting line < ending line -- downward selection. */
 | 
				
			||||||
 | 
								if (py < sel->sy || py > sel->ey)
 | 
				
			||||||
 | 
									return (0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if ((py == sel->sy && px < sel->sx)
 | 
				
			||||||
 | 
								    || (py == sel->ey && px > sel->ex))
 | 
				
			||||||
 | 
									return (0);
 | 
				
			||||||
 | 
							} else if (sel->sy > sel->ey) {
 | 
				
			||||||
 | 
								/* starting line > ending line -- upward selection. */
 | 
				
			||||||
 | 
								if (py > sel->sy || py < sel->ey)
 | 
				
			||||||
 | 
									return (0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if ((py == sel->sy && px >= sel->sx)
 | 
				
			||||||
 | 
								    || (py == sel->ey && px < sel->ex))
 | 
				
			||||||
 | 
									return (0);
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								/* starting line == ending line. */
 | 
				
			||||||
 | 
								if (py != sel->sy)
 | 
				
			||||||
 | 
									return (0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (sel->ex < sel->sx) {
 | 
				
			||||||
 | 
									/* cursor (ex) is on the left */
 | 
				
			||||||
 | 
									if (px > sel->sx || px < sel->ex)
 | 
				
			||||||
 | 
										return (0);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									/* selection start (sx) is on the left */
 | 
				
			||||||
 | 
									if (px < sel->sx || px > sel->ex)
 | 
				
			||||||
 | 
										return (0);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((py == sel->sy && px < sel->sx) || (py == sel->ey && px > sel->ex))
 | 
					 | 
				
			||||||
		return (0);
 | 
					 | 
				
			||||||
	return (1);
 | 
						return (1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								tmux.1
									
									
									
									
									
								
							@@ -564,6 +564,7 @@ The following keys are supported as appropriate for the mode:
 | 
				
			|||||||
.It Li "Previous word" Ta "b" Ta "M-b"
 | 
					.It Li "Previous word" Ta "b" Ta "M-b"
 | 
				
			||||||
.It Li "Previous space" Ta "B" Ta ""
 | 
					.It Li "Previous space" Ta "B" Ta ""
 | 
				
			||||||
.It Li "Quit mode" Ta "q" Ta "Escape"
 | 
					.It Li "Quit mode" Ta "q" Ta "Escape"
 | 
				
			||||||
 | 
					.It Li "Rectangle toggle" Ta "v" Ta "R"
 | 
				
			||||||
.It Li "Scroll down" Ta "C-Down or C-e" Ta "C-Down"
 | 
					.It Li "Scroll down" Ta "C-Down or C-e" Ta "C-Down"
 | 
				
			||||||
.It Li "Scroll up" Ta "C-Up or C-y" Ta "C-Up"
 | 
					.It Li "Scroll up" Ta "C-Up or C-y" Ta "C-Up"
 | 
				
			||||||
.It Li "Search again" Ta "n" Ta "n"
 | 
					.It Li "Search again" Ta "n" Ta "n"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										6
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								tmux.h
									
									
									
									
									
								
							@@ -469,6 +469,7 @@ enum mode_key_cmd {
 | 
				
			|||||||
	MODEKEYCOPY_PREVIOUSPAGE,
 | 
						MODEKEYCOPY_PREVIOUSPAGE,
 | 
				
			||||||
	MODEKEYCOPY_PREVIOUSSPACE,
 | 
						MODEKEYCOPY_PREVIOUSSPACE,
 | 
				
			||||||
	MODEKEYCOPY_PREVIOUSWORD,
 | 
						MODEKEYCOPY_PREVIOUSWORD,
 | 
				
			||||||
 | 
						MODEKEYCOPY_RECTANGLETOGGLE,
 | 
				
			||||||
	MODEKEYCOPY_RIGHT,
 | 
						MODEKEYCOPY_RIGHT,
 | 
				
			||||||
	MODEKEYCOPY_SCROLLDOWN,
 | 
						MODEKEYCOPY_SCROLLDOWN,
 | 
				
			||||||
	MODEKEYCOPY_SCROLLUP,
 | 
						MODEKEYCOPY_SCROLLUP,
 | 
				
			||||||
@@ -674,6 +675,7 @@ SLIST_HEAD(joblist, job);
 | 
				
			|||||||
/* Screen selection. */
 | 
					/* Screen selection. */
 | 
				
			||||||
struct screen_sel {
 | 
					struct screen_sel {
 | 
				
			||||||
	int		 flag;
 | 
						int		 flag;
 | 
				
			||||||
 | 
						int		 rectflag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	u_int		 sx;
 | 
						u_int		 sx;
 | 
				
			||||||
	u_int		 sy;
 | 
						u_int		 sy;
 | 
				
			||||||
@@ -1774,8 +1776,8 @@ void	 screen_free(struct screen *);
 | 
				
			|||||||
void	 screen_reset_tabs(struct screen *);
 | 
					void	 screen_reset_tabs(struct screen *);
 | 
				
			||||||
void	 screen_set_title(struct screen *, const char *);
 | 
					void	 screen_set_title(struct screen *, const char *);
 | 
				
			||||||
void	 screen_resize(struct screen *, u_int, u_int);
 | 
					void	 screen_resize(struct screen *, u_int, u_int);
 | 
				
			||||||
void	 screen_set_selection(
 | 
					void	 screen_set_selection(struct screen *,
 | 
				
			||||||
	     struct screen *, u_int, u_int, u_int, u_int, struct grid_cell *);
 | 
						     u_int, u_int, u_int, u_int, u_int, struct grid_cell *);
 | 
				
			||||||
void	 screen_clear_selection(struct screen *);
 | 
					void	 screen_clear_selection(struct screen *);
 | 
				
			||||||
int	 screen_check_selection(struct screen *, u_int, u_int);
 | 
					int	 screen_check_selection(struct screen *, u_int, u_int);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										112
									
								
								window-copy.c
									
									
									
									
									
								
							
							
						
						
									
										112
									
								
								window-copy.c
									
									
									
									
									
								
							@@ -68,6 +68,7 @@ void	window_copy_cursor_next_word_end(struct window_pane *, const char *);
 | 
				
			|||||||
void	window_copy_cursor_previous_word(struct window_pane *, const char *);
 | 
					void	window_copy_cursor_previous_word(struct window_pane *, const char *);
 | 
				
			||||||
void	window_copy_scroll_up(struct window_pane *, u_int);
 | 
					void	window_copy_scroll_up(struct window_pane *, u_int);
 | 
				
			||||||
void	window_copy_scroll_down(struct window_pane *, u_int);
 | 
					void	window_copy_scroll_down(struct window_pane *, u_int);
 | 
				
			||||||
 | 
					void	window_copy_rectangle_toggle(struct window_pane *);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const struct window_mode window_copy_mode = {
 | 
					const struct window_mode window_copy_mode = {
 | 
				
			||||||
	window_copy_init,
 | 
						window_copy_init,
 | 
				
			||||||
@@ -95,6 +96,8 @@ struct window_copy_mode_data {
 | 
				
			|||||||
	u_int		selx;
 | 
						u_int		selx;
 | 
				
			||||||
	u_int		sely;
 | 
						u_int		sely;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						u_int		rectflag; /* are we in rectangle copy mode? */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	u_int		cx;
 | 
						u_int		cx;
 | 
				
			||||||
	u_int		cy;
 | 
						u_int		cy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -126,6 +129,8 @@ window_copy_init(struct window_pane *wp)
 | 
				
			|||||||
	data->lastcx = 0;
 | 
						data->lastcx = 0;
 | 
				
			||||||
	data->lastsx = 0;
 | 
						data->lastsx = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data->rectflag = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	data->inputtype = WINDOW_COPY_OFF;
 | 
						data->inputtype = WINDOW_COPY_OFF;
 | 
				
			||||||
	data->inputprompt = NULL;
 | 
						data->inputprompt = NULL;
 | 
				
			||||||
	data->inputstr = xstrdup("");
 | 
						data->inputstr = xstrdup("");
 | 
				
			||||||
@@ -379,6 +384,9 @@ window_copy_key(struct window_pane *wp, struct client *c, int key)
 | 
				
			|||||||
		data->inputprompt = "Goto Line";
 | 
							data->inputprompt = "Goto Line";
 | 
				
			||||||
		*data->inputstr = '\0';
 | 
							*data->inputstr = '\0';
 | 
				
			||||||
		goto input_on;
 | 
							goto input_on;
 | 
				
			||||||
 | 
						case MODEKEYCOPY_RECTANGLETOGGLE:
 | 
				
			||||||
 | 
							window_copy_rectangle_toggle(wp);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -823,7 +831,7 @@ window_copy_update_selection(struct window_pane *wp)
 | 
				
			|||||||
	struct screen			*s = &data->screen;
 | 
						struct screen			*s = &data->screen;
 | 
				
			||||||
	struct options			*oo = &wp->window->options;
 | 
						struct options			*oo = &wp->window->options;
 | 
				
			||||||
	struct grid_cell		 gc;
 | 
						struct grid_cell		 gc;
 | 
				
			||||||
	u_int				 sx, sy, ty;
 | 
						u_int				 sx, sy, ty, cy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!s->sel.flag)
 | 
						if (!s->sel.flag)
 | 
				
			||||||
		return (0);
 | 
							return (0);
 | 
				
			||||||
@@ -841,17 +849,33 @@ window_copy_update_selection(struct window_pane *wp)
 | 
				
			|||||||
	sx = data->selx;
 | 
						sx = data->selx;
 | 
				
			||||||
	sy = data->sely;
 | 
						sy = data->sely;
 | 
				
			||||||
	if (sy < ty) {					/* above screen */
 | 
						if (sy < ty) {					/* above screen */
 | 
				
			||||||
		sx = 0;
 | 
							if (!data->rectflag)
 | 
				
			||||||
 | 
								sx = 0;
 | 
				
			||||||
		sy = 0;
 | 
							sy = 0;
 | 
				
			||||||
	} else if (sy > ty + screen_size_y(s) - 1) {	/* below screen */
 | 
						} else if (sy > ty + screen_size_y(s) - 1) {	/* below screen */
 | 
				
			||||||
		sx = screen_size_x(s) - 1;
 | 
							if (!data->rectflag)
 | 
				
			||||||
 | 
								sx = screen_size_x(s) - 1;
 | 
				
			||||||
		sy = screen_size_y(s) - 1;
 | 
							sy = screen_size_y(s) - 1;
 | 
				
			||||||
	} else
 | 
						} else
 | 
				
			||||||
		sy -= ty;
 | 
							sy -= ty;
 | 
				
			||||||
	sy = screen_hsize(s) + sy;
 | 
						sy = screen_hsize(s) + sy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	screen_set_selection(
 | 
						screen_set_selection(s,
 | 
				
			||||||
	    s, sx, sy, data->cx, screen_hsize(s) + data->cy, &gc);
 | 
						    sx, sy, data->cx, screen_hsize(s) + data->cy, data->rectflag, &gc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (data->rectflag) {
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Can't rely on the caller to redraw the right lines for
 | 
				
			||||||
 | 
							 * rectangle selection - find the highest line and the number
 | 
				
			||||||
 | 
							 * of lines, and redraw just past that in both directions
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							cy = data->cy;
 | 
				
			||||||
 | 
							if (sy < cy)
 | 
				
			||||||
 | 
								window_copy_redraw_lines(wp, sy, cy - sy + 1);
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								window_copy_redraw_lines(wp, cy, sy - cy + 1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return (1);
 | 
						return (1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -861,8 +885,9 @@ window_copy_copy_selection(struct window_pane *wp, struct client *c)
 | 
				
			|||||||
	struct window_copy_mode_data	*data = wp->modedata;
 | 
						struct window_copy_mode_data	*data = wp->modedata;
 | 
				
			||||||
	struct screen			*s = &data->screen;
 | 
						struct screen			*s = &data->screen;
 | 
				
			||||||
	char				*buf;
 | 
						char				*buf;
 | 
				
			||||||
	size_t	 			 off;
 | 
						size_t				 off;
 | 
				
			||||||
	u_int	 			 i, xx, yy, sx, sy, ex, ey, limit;
 | 
						u_int				 i, xx, yy, sx, sy, ex, ey, limit;
 | 
				
			||||||
 | 
						u_int				 firstsx, lastex, restex, restsx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!s->sel.flag)
 | 
						if (!s->sel.flag)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
@@ -893,17 +918,53 @@ window_copy_copy_selection(struct window_pane *wp, struct client *c)
 | 
				
			|||||||
	if (ex > xx)
 | 
						if (ex > xx)
 | 
				
			||||||
		ex = xx;
 | 
							ex = xx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Deal with rectangle-copy if necessary; four situations: start of
 | 
				
			||||||
 | 
						 * first line (firstsx), end of last line (lastex), start (restsx) and
 | 
				
			||||||
 | 
						 * end (restex) of all other lines.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						xx = screen_size_x(s);
 | 
				
			||||||
 | 
						if (data->rectflag) {
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Need to ignore the column with the cursor in it, which for
 | 
				
			||||||
 | 
							 * rectangular copy means knowing which side the cursor is on.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							if (data->selx < data->cx) {
 | 
				
			||||||
 | 
								/* Selection start is on the left. */
 | 
				
			||||||
 | 
								lastex = data->cx;
 | 
				
			||||||
 | 
								restex = data->cx;
 | 
				
			||||||
 | 
								firstsx = data->selx;
 | 
				
			||||||
 | 
								restsx = data->selx;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								/* Cursor is on the left. */
 | 
				
			||||||
 | 
								lastex = data->selx + 1;
 | 
				
			||||||
 | 
								restex = data->selx + 1;
 | 
				
			||||||
 | 
								firstsx = data->cx + 1;
 | 
				
			||||||
 | 
								restsx = data->cx + 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							/*
 | 
				
			||||||
 | 
							 * Like emacs, keep the top-left-most character, and drop the
 | 
				
			||||||
 | 
							 * bottom-right-most, regardless of copy direction.
 | 
				
			||||||
 | 
							 */
 | 
				
			||||||
 | 
							lastex = ex;
 | 
				
			||||||
 | 
							restex = xx;
 | 
				
			||||||
 | 
							firstsx = sx;
 | 
				
			||||||
 | 
							restsx = 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Copy the lines. */
 | 
						/* Copy the lines. */
 | 
				
			||||||
	if (sy == ey)
 | 
						if (sy == ey)
 | 
				
			||||||
		window_copy_copy_line(wp, &buf, &off, sy, sx, ex);
 | 
							window_copy_copy_line(wp, &buf, &off, sy, firstsx, lastex);
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		xx = screen_size_x(s);
 | 
							window_copy_copy_line(wp, &buf, &off, sy, firstsx, restex);
 | 
				
			||||||
		window_copy_copy_line(wp, &buf, &off, sy, sx, xx);
 | 
					 | 
				
			||||||
		if (ey - sy > 1) {
 | 
							if (ey - sy > 1) {
 | 
				
			||||||
			for (i = sy + 1; i < ey; i++)
 | 
								for (i = sy + 1; i < ey; i++) {
 | 
				
			||||||
				window_copy_copy_line(wp, &buf, &off, i, 0, xx);
 | 
									window_copy_copy_line(
 | 
				
			||||||
 | 
									    wp, &buf, &off, i, restsx, restex);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		window_copy_copy_line(wp, &buf, &off, ey, 0, ex);
 | 
							window_copy_copy_line(wp, &buf, &off, ey, restsx, lastex);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Don't bother if no data. */
 | 
						/* Don't bother if no data. */
 | 
				
			||||||
@@ -1288,7 +1349,6 @@ window_copy_scroll_up(struct window_pane *wp, u_int ny)
 | 
				
			|||||||
	if (ny == 0)
 | 
						if (ny == 0)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	data->oy -= ny;
 | 
						data->oy -= ny;
 | 
				
			||||||
	window_copy_update_selection(wp);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	screen_write_start(&ctx, wp, NULL);
 | 
						screen_write_start(&ctx, wp, NULL);
 | 
				
			||||||
	screen_write_cursormove(&ctx, 0, 0);
 | 
						screen_write_cursormove(&ctx, 0, 0);
 | 
				
			||||||
@@ -1299,9 +1359,12 @@ window_copy_scroll_up(struct window_pane *wp, u_int ny)
 | 
				
			|||||||
		window_copy_write_line(wp, &ctx, 1);
 | 
							window_copy_write_line(wp, &ctx, 1);
 | 
				
			||||||
	if (screen_size_y(s) > 3)
 | 
						if (screen_size_y(s) > 3)
 | 
				
			||||||
		window_copy_write_line(wp, &ctx, screen_size_y(s) - 2);
 | 
							window_copy_write_line(wp, &ctx, screen_size_y(s) - 2);
 | 
				
			||||||
	if (s->sel.flag && screen_size_y(s) > ny)
 | 
						if (s->sel.flag && screen_size_y(s) > ny) {
 | 
				
			||||||
 | 
							window_copy_update_selection(wp);
 | 
				
			||||||
		window_copy_write_line(wp, &ctx, screen_size_y(s) - ny - 1);
 | 
							window_copy_write_line(wp, &ctx, screen_size_y(s) - ny - 1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	screen_write_cursormove(&ctx, data->cx, data->cy);
 | 
						screen_write_cursormove(&ctx, data->cx, data->cy);
 | 
				
			||||||
 | 
						window_copy_update_selection(wp);
 | 
				
			||||||
	screen_write_stop(&ctx);
 | 
						screen_write_stop(&ctx);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1320,16 +1383,29 @@ window_copy_scroll_down(struct window_pane *wp, u_int ny)
 | 
				
			|||||||
	if (ny == 0)
 | 
						if (ny == 0)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	data->oy += ny;
 | 
						data->oy += ny;
 | 
				
			||||||
	window_copy_update_selection(wp);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	screen_write_start(&ctx, wp, NULL);
 | 
						screen_write_start(&ctx, wp, NULL);
 | 
				
			||||||
	screen_write_cursormove(&ctx, 0, 0);
 | 
						screen_write_cursormove(&ctx, 0, 0);
 | 
				
			||||||
	screen_write_insertline(&ctx, ny);
 | 
						screen_write_insertline(&ctx, ny);
 | 
				
			||||||
	window_copy_write_lines(wp, &ctx, 0, ny);
 | 
						window_copy_write_lines(wp, &ctx, 0, ny);
 | 
				
			||||||
	if (s->sel.flag && screen_size_y(s) > ny)
 | 
						if (s->sel.flag && screen_size_y(s) > ny) {
 | 
				
			||||||
 | 
							window_copy_update_selection(wp);
 | 
				
			||||||
		window_copy_write_line(wp, &ctx, ny);
 | 
							window_copy_write_line(wp, &ctx, ny);
 | 
				
			||||||
	else if (ny == 1) /* nuke position */
 | 
						} else if (ny == 1) /* nuke position */
 | 
				
			||||||
		window_copy_write_line(wp, &ctx, 1);
 | 
							window_copy_write_line(wp, &ctx, 1);
 | 
				
			||||||
	screen_write_cursormove(&ctx, data->cx, data->cy);
 | 
						screen_write_cursormove(&ctx, data->cx, data->cy);
 | 
				
			||||||
 | 
						window_copy_update_selection(wp);
 | 
				
			||||||
	screen_write_stop(&ctx);
 | 
						screen_write_stop(&ctx);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void
 | 
				
			||||||
 | 
					window_copy_rectangle_toggle(struct window_pane *wp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct window_copy_mode_data	*data = wp->modedata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data->rectflag = !data->rectflag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						window_copy_update_selection(wp);
 | 
				
			||||||
 | 
						window_copy_redraw_screen(wp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user