summaryrefslogtreecommitdiff
path: root/usr.bin/tmux/window-copy.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/tmux/window-copy.c')
-rw-r--r--usr.bin/tmux/window-copy.c114
1 files changed, 95 insertions, 19 deletions
diff --git a/usr.bin/tmux/window-copy.c b/usr.bin/tmux/window-copy.c
index 9f17a0de50a..f0dd8eb3596 100644
--- a/usr.bin/tmux/window-copy.c
+++ b/usr.bin/tmux/window-copy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: window-copy.c,v 1.41 2010/02/04 20:00:26 nicm Exp $ */
+/* $OpenBSD: window-copy.c,v 1.42 2010/02/06 17:35:01 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
@@ -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_scroll_up(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 = {
window_copy_init,
@@ -95,6 +96,8 @@ struct window_copy_mode_data {
u_int selx;
u_int sely;
+ u_int rectflag; /* are we in rectangle copy mode? */
+
u_int cx;
u_int cy;
@@ -126,6 +129,8 @@ window_copy_init(struct window_pane *wp)
data->lastcx = 0;
data->lastsx = 0;
+ data->rectflag = 0;
+
data->inputtype = WINDOW_COPY_OFF;
data->inputprompt = NULL;
data->inputstr = xstrdup("");
@@ -379,6 +384,9 @@ window_copy_key(struct window_pane *wp, struct client *c, int key)
data->inputprompt = "Goto Line";
*data->inputstr = '\0';
goto input_on;
+ case MODEKEYCOPY_RECTANGLETOGGLE:
+ window_copy_rectangle_toggle(wp);
+ return;
default:
break;
}
@@ -823,7 +831,7 @@ window_copy_update_selection(struct window_pane *wp)
struct screen *s = &data->screen;
struct options *oo = &wp->window->options;
struct grid_cell gc;
- u_int sx, sy, ty;
+ u_int sx, sy, ty, cy;
if (!s->sel.flag)
return (0);
@@ -841,17 +849,33 @@ window_copy_update_selection(struct window_pane *wp)
sx = data->selx;
sy = data->sely;
if (sy < ty) { /* above screen */
- sx = 0;
+ if (!data->rectflag)
+ sx = 0;
sy = 0;
} 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;
} else
sy -= ty;
sy = screen_hsize(s) + sy;
- screen_set_selection(
- s, sx, sy, data->cx, screen_hsize(s) + data->cy, &gc);
+ screen_set_selection(s,
+ 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);
}
@@ -861,8 +885,9 @@ window_copy_copy_selection(struct window_pane *wp, struct client *c)
struct window_copy_mode_data *data = wp->modedata;
struct screen *s = &data->screen;
char *buf;
- size_t off;
- u_int i, xx, yy, sx, sy, ex, ey, limit;
+ size_t off;
+ u_int i, xx, yy, sx, sy, ex, ey, limit;
+ u_int firstsx, lastex, restex, restsx;
if (!s->sel.flag)
return;
@@ -893,17 +918,53 @@ window_copy_copy_selection(struct window_pane *wp, struct client *c)
if (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. */
if (sy == ey)
- window_copy_copy_line(wp, &buf, &off, sy, sx, ex);
+ window_copy_copy_line(wp, &buf, &off, sy, firstsx, lastex);
else {
- xx = screen_size_x(s);
- window_copy_copy_line(wp, &buf, &off, sy, sx, xx);
+ window_copy_copy_line(wp, &buf, &off, sy, firstsx, restex);
if (ey - sy > 1) {
- for (i = sy + 1; i < ey; i++)
- window_copy_copy_line(wp, &buf, &off, i, 0, xx);
+ for (i = sy + 1; i < ey; i++) {
+ 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. */
@@ -1288,7 +1349,6 @@ window_copy_scroll_up(struct window_pane *wp, u_int ny)
if (ny == 0)
return;
data->oy -= ny;
- window_copy_update_selection(wp);
screen_write_start(&ctx, wp, NULL);
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);
if (screen_size_y(s) > 3)
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);
+ }
screen_write_cursormove(&ctx, data->cx, data->cy);
+ window_copy_update_selection(wp);
screen_write_stop(&ctx);
}
@@ -1320,16 +1383,29 @@ window_copy_scroll_down(struct window_pane *wp, u_int ny)
if (ny == 0)
return;
data->oy += ny;
- window_copy_update_selection(wp);
screen_write_start(&ctx, wp, NULL);
screen_write_cursormove(&ctx, 0, 0);
screen_write_insertline(&ctx, 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);
- else if (ny == 1) /* nuke position */
+ } else if (ny == 1) /* nuke position */
window_copy_write_line(wp, &ctx, 1);
screen_write_cursormove(&ctx, data->cx, data->cy);
+ window_copy_update_selection(wp);
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);
+}
+