diff options
author | Thomas Adam <thomas@xteddy.org> | 2019-04-02 11:02:44 +0100 |
---|---|---|
committer | Thomas Adam <thomas@xteddy.org> | 2019-04-02 11:02:44 +0100 |
commit | bfc1f0ca62356e1e32e34baa1f8ade168fa72de0 (patch) | |
tree | ee0c4542d22df704aea440e468cc923a96462af5 | |
parent | f03776c262ff68f4f5c3fefefd559256d534179d (diff) | |
parent | 7bcc0d16f24506bed6568ba36bcd278cfc06d069 (diff) |
Merge branch 'obsd-master'
-rw-r--r-- | grid.c | 71 | ||||
-rw-r--r-- | input.c | 2 | ||||
-rw-r--r-- | paste.c | 9 | ||||
-rw-r--r-- | screen.c | 8 | ||||
-rw-r--r-- | tmux.1 | 21 | ||||
-rw-r--r-- | tmux.h | 6 | ||||
-rw-r--r-- | tty-keys.c | 2 | ||||
-rw-r--r-- | window-copy.c | 141 |
8 files changed, 179 insertions, 81 deletions
@@ -1291,40 +1291,61 @@ grid_reflow(struct grid *gd, u_int sx) free(target); } -/* Convert point position to offset from the start of the grid. */ -u_int -grid_to_offset(struct grid *gd, u_int px, u_int py) +/* Convert to position based on wrapped lines. */ +void +grid_wrap_position(struct grid *gd, u_int px, u_int py, u_int *wx, u_int *wy) { - u_int yy, offset = 0; - - if (py > gd->hsize + gd->sy - 1) { - px = UINT_MAX; - py = gd->hsize + gd->sy - 1; + u_int ax = 0, ay = 0, yy; + + for (yy = 0; yy < py; yy++) { + if (gd->linedata[yy].flags & GRID_LINE_WRAPPED) + ax += gd->linedata[yy].cellused; + else { + ax = 0; + ay++; + } } - - for (yy = 0; yy < py; yy++) - offset += gd->linedata[yy].cellused; - if (px > gd->linedata[yy].cellused) - px = gd->linedata[yy].cellused; - return (offset + px); + if (px >= gd->linedata[yy].cellused) + ax = UINT_MAX; + else + ax += px; + *wx = ax; + *wy = ay; } -/* Convert offset from the start of the grid to point position. */ +/* Convert position based on wrapped lines back. */ void -grid_from_offset(struct grid *gd, u_int offset, u_int *px, u_int *py) +grid_unwrap_position(struct grid *gd, u_int *px, u_int *py, u_int wx, u_int wy) { - u_int yy; - - *px = *py = 0; + u_int yy, ax = 0, ay = 0; for (yy = 0; yy < gd->hsize + gd->sy - 1; yy++) { - if (offset <= gd->linedata[yy].cellused) + if (ay == wy) break; - offset -= gd->linedata[yy].cellused; + if (gd->linedata[yy].flags & GRID_LINE_WRAPPED) + ax += gd->linedata[yy].cellused; + else { + ax = 0; + ay++; + } } - if (offset < gd->linedata[yy].cellused) - *px = offset; - else - *px = gd->linedata[yy].cellused; + + /* + * yy is now 0 on the unwrapped line which contains wx. Walk forwards + * until we find the end or the line now containing wx. + */ + if (wx == UINT_MAX) { + while (gd->linedata[yy].flags & GRID_LINE_WRAPPED) + yy++; + wx = gd->linedata[yy].cellused; + } else { + while (gd->linedata[yy].flags & GRID_LINE_WRAPPED) { + if (wx < gd->linedata[yy].cellused) + break; + wx -= gd->linedata[yy].cellused; + yy++; + } + } + *px = wx; *py = yy; } @@ -2432,7 +2432,7 @@ input_osc_52(struct input_ctx *ictx, const char *p) screen_write_stop(&ctx); notify_pane("pane-set-clipboard", wp); - paste_add(out, outlen); + paste_add(NULL, out, outlen); } /* Handle the OSC 104 sequence for unsetting (multiple) palette entries. */ @@ -157,11 +157,14 @@ paste_free(struct paste_buffer *pb) * that the caller is responsible for allocating data. */ void -paste_add(char *data, size_t size) +paste_add(const char *prefix, char *data, size_t size) { struct paste_buffer *pb, *pb1; u_int limit; + if (prefix == NULL) + prefix = "buffer"; + if (size == 0) { free(data); return; @@ -180,7 +183,7 @@ paste_add(char *data, size_t size) pb->name = NULL; do { free(pb->name); - xasprintf(&pb->name, "buffer%04u", paste_next_index); + xasprintf(&pb->name, "%s%u", prefix, paste_next_index); paste_next_index++; } while (paste_get_name(pb->name) != NULL); @@ -262,7 +265,7 @@ paste_set(char *data, size_t size, const char *name, char **cause) return (0); } if (name == NULL) { - paste_add(data, size); + paste_add(NULL, data, size); return (0); } @@ -463,17 +463,17 @@ screen_select_cell(struct screen *s, struct grid_cell *dst, static void screen_reflow(struct screen *s, u_int new_x) { - u_int offset, cx = s->cx, cy = s->grid->hsize + s->cy; + u_int cx = s->cx, cy = s->grid->hsize + s->cy, wx, wy; struct timeval start, tv; gettimeofday(&start, NULL); - offset = grid_to_offset(s->grid, cx, cy); - log_debug("%s: cursor %u,%u offset is %u", __func__, cx, cy, offset); + 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_from_offset(s->grid, offset, &cx, &cy); + 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) { @@ -1175,12 +1175,12 @@ The following commands are supported in copy mode: .It Li "bottom-line" Ta "L" Ta "" .It Li "cancel" Ta "q" Ta "Escape" .It Li "clear-selection" Ta "Escape" Ta "C-g" -.It Li "copy-end-of-line" Ta "D" Ta "C-k" -.It Li "copy-line" Ta "" Ta "" -.It Li "copy-pipe <command>" Ta "" Ta "" -.It Li "copy-pipe-and-cancel <command>" Ta "" Ta "" -.It Li "copy-selection" Ta "" Ta "" -.It Li "copy-selection-and-cancel" Ta "Enter" Ta "M-w" +.It Li "copy-end-of-line [<prefix>]" Ta "D" Ta "C-k" +.It Li "copy-line [<prefix>]" Ta "" Ta "" +.It Li "copy-pipe <command> [<prefix>]" Ta "" Ta "" +.It Li "copy-pipe-and-cancel <command> [<prefix>]" Ta "" Ta "" +.It Li "copy-selection [<prefix>]" Ta "" Ta "" +.It Li "copy-selection-and-cancel [<prefix>]" Ta "Enter" Ta "M-w" .It Li "cursor-down" Ta "j" Ta "Down" .It Li "cursor-left" Ta "h" Ta "Left" .It Li "cursor-right" Ta "l" Ta "Right" @@ -1227,6 +1227,15 @@ The following commands are supported in copy mode: .It Li "top-line" Ta "H" Ta "M-R" .El .Pp +Copy commands may take an optional buffer prefix argument which is used +to generate the buffer name (the default is +.Ql buffer +so buffers are named +.Ql buffer0 , +.Ql buffer1 +and so on). +Pipe commands take a command argument which is the command to which the +copied text is piped. The .Ql -and-cancel variants of some commands exit copy mode after they have completed (for copy @@ -1613,7 +1613,7 @@ struct paste_buffer *paste_walk(struct paste_buffer *); struct paste_buffer *paste_get_top(const char **); struct paste_buffer *paste_get_name(const char *); void paste_free(struct paste_buffer *); -void paste_add(char *, size_t); +void paste_add(const char *, char *, size_t); int paste_rename(const char *, const char *, char **); int paste_set(char *, size_t, const char *, char **); char *paste_make_sample(struct paste_buffer *); @@ -2103,8 +2103,8 @@ char *grid_string_cells(struct grid *, u_int, u_int, u_int, void grid_duplicate_lines(struct grid *, u_int, struct grid *, u_int, u_int); void grid_reflow(struct grid *, u_int); -u_int grid_to_offset(struct grid *, u_int, u_int); -void grid_from_offset(struct grid *, u_int, u_int *, u_int *); +void grid_wrap_position(struct grid *, u_int, u_int, u_int *, u_int *); +void grid_unwrap_position(struct grid *, u_int *, u_int *, u_int, u_int); /* grid-view.c */ void grid_view_get_cell(struct grid *, u_int, u_int, struct grid_cell *); @@ -976,7 +976,7 @@ tty_keys_clipboard(__unused struct tty *tty, const char *buf, size_t len, /* Create a new paste buffer. */ log_debug("%s: %.*s", __func__, outlen, out); - paste_add(out, outlen); + paste_add(NULL, out, outlen); return (0); } diff --git a/window-copy.c b/window-copy.c index b4fc7a2c..aacea5c5 100644 --- a/window-copy.c +++ b/window-copy.c @@ -79,11 +79,12 @@ static int window_copy_set_selection(struct window_mode_entry *, int); static int window_copy_update_selection(struct window_mode_entry *, int); static void window_copy_synchronize_cursor(struct window_mode_entry *); static void *window_copy_get_selection(struct window_mode_entry *, size_t *); -static void window_copy_copy_buffer(struct window_mode_entry *, void *, - size_t); +static void window_copy_copy_buffer(struct window_mode_entry *, + const char *, void *, size_t); static void window_copy_copy_pipe(struct window_mode_entry *, - struct session *, const char *); -static void window_copy_copy_selection(struct window_mode_entry *); + struct session *, const char *, const char *); +static void window_copy_copy_selection(struct window_mode_entry *, + const char *); static void window_copy_append_selection(struct window_mode_entry *); static void window_copy_clear_selection(struct window_mode_entry *); static void window_copy_copy_line(struct window_mode_entry *, char **, @@ -164,8 +165,10 @@ struct window_copy_cmd_state { struct window_mode_entry *wme; struct args *args; struct mouse_event *m; + struct client *c; struct session *s; + struct winlink *wl; }; /* @@ -673,8 +676,15 @@ static enum window_copy_cmd_action window_copy_cmd_copy_end_of_line(struct window_copy_cmd_state *cs) { struct window_mode_entry *wme = cs->wme; + struct client *c = cs->c; struct session *s = cs->s; + struct winlink *wl = cs->wl; + struct window_pane *wp = wme->wp; u_int np = wme->prefix; + char *prefix = NULL; + + if (cs->args->argc == 2) + prefix = format_single(NULL, cs->args->argv[1], c, s, wl, wp); window_copy_start_selection(wme); for (; np > 1; np--) @@ -682,9 +692,13 @@ window_copy_cmd_copy_end_of_line(struct window_copy_cmd_state *cs) window_copy_cursor_end_of_line(wme); if (s != NULL) { - window_copy_copy_selection(wme); + window_copy_copy_selection(wme, prefix); + + free(prefix); return (WINDOW_COPY_CMD_CANCEL); } + + free(prefix); return (WINDOW_COPY_CMD_REDRAW); } @@ -692,8 +706,15 @@ static enum window_copy_cmd_action window_copy_cmd_copy_line(struct window_copy_cmd_state *cs) { struct window_mode_entry *wme = cs->wme; + struct client *c = cs->c; struct session *s = cs->s; + struct winlink *wl = cs->wl; + struct window_pane *wp = wme->wp; u_int np = wme->prefix; + char *prefix = NULL; + + if (cs->args->argc == 2) + prefix = format_single(NULL, cs->args->argv[1], c, s, wl, wp); window_copy_cursor_start_of_line(wme); window_copy_start_selection(wme); @@ -702,9 +723,13 @@ window_copy_cmd_copy_line(struct window_copy_cmd_state *cs) window_copy_cursor_end_of_line(wme); if (s != NULL) { - window_copy_copy_selection(wme); + window_copy_copy_selection(wme, prefix); + + free(prefix); return (WINDOW_COPY_CMD_CANCEL); } + + free(prefix); return (WINDOW_COPY_CMD_REDRAW); } @@ -712,11 +737,20 @@ static enum window_copy_cmd_action window_copy_cmd_copy_selection(struct window_copy_cmd_state *cs) { struct window_mode_entry *wme = cs->wme; + struct client *c = cs->c; struct session *s = cs->s; + struct winlink *wl = cs->wl; + struct window_pane *wp = wme->wp; + char *prefix = NULL; + + if (cs->args->argc == 2) + prefix = format_single(NULL, cs->args->argv[1], c, s, wl, wp); if (s != NULL) - window_copy_copy_selection(wme); + window_copy_copy_selection(wme, prefix); window_copy_clear_selection(wme); + + free(prefix); return (WINDOW_COPY_CMD_REDRAW); } @@ -724,11 +758,20 @@ static enum window_copy_cmd_action window_copy_cmd_copy_selection_and_cancel(struct window_copy_cmd_state *cs) { struct window_mode_entry *wme = cs->wme; + struct client *c = cs->c; struct session *s = cs->s; + struct winlink *wl = cs->wl; + struct window_pane *wp = wme->wp; + char *prefix = NULL; + + if (cs->args->argc == 2) + prefix = format_single(NULL, cs->args->argv[1], c, s, wl, wp); if (s != NULL) - window_copy_copy_selection(wme); + window_copy_copy_selection(wme, prefix); window_copy_clear_selection(wme); + + free(prefix); return (WINDOW_COPY_CMD_CANCEL); } @@ -1216,11 +1259,23 @@ static enum window_copy_cmd_action window_copy_cmd_copy_pipe(struct window_copy_cmd_state *cs) { struct window_mode_entry *wme = cs->wme; + struct client *c = cs->c; struct session *s = cs->s; - const char *argument = cs->args->argv[1]; + struct winlink *wl = cs->wl; + struct window_pane *wp = wme->wp; + char *command = NULL; + char *prefix = NULL; + + if (cs->args->argc == 3) + prefix = format_single(NULL, cs->args->argv[2], c, s, wl, wp); - if (s != NULL && *argument != '\0') - window_copy_copy_pipe(wme, s, argument); + if (s != NULL && *cs->args->argv[1] != '\0') { + command = format_single(NULL, cs->args->argv[1], c, s, wl, wp); + window_copy_copy_pipe(wme, s, prefix, command); + free(command); + } + + free(prefix); return (WINDOW_COPY_CMD_NOTHING); } @@ -1228,13 +1283,26 @@ static enum window_copy_cmd_action window_copy_cmd_copy_pipe_and_cancel(struct window_copy_cmd_state *cs) { struct window_mode_entry *wme = cs->wme; + struct client *c = cs->c; struct session *s = cs->s; - const char *argument = cs->args->argv[1]; + struct winlink *wl = cs->wl; + struct window_pane *wp = wme->wp; + char *command = NULL; + char *prefix = NULL; + + if (cs->args->argc == 3) + prefix = format_single(NULL, cs->args->argv[2], c, s, wl, wp); + + if (s != NULL && *cs->args->argv[1] != '\0') { + command = format_single(NULL, cs->args->argv[1], c, s, wl, wp); + window_copy_copy_pipe(wme, s, prefix, command); + free(command); - if (s != NULL && *argument != '\0') { - window_copy_copy_pipe(wme, s, argument); + free(prefix); return (WINDOW_COPY_CMD_CANCEL); } + + free(prefix); return (WINDOW_COPY_CMD_NOTHING); } @@ -1278,7 +1346,7 @@ window_copy_cmd_jump_forward(struct window_copy_cmd_state *cs) data->jumptype = WINDOW_COPY_JUMPFORWARD; data->jumpchar = *argument; for (; np != 0; np--) - window_copy_cursor_jump(wme); + window_copy_cursor_jump(wme); } return (WINDOW_COPY_CMD_NOTHING); } @@ -1470,17 +1538,17 @@ static const struct { window_copy_cmd_cancel }, { "clear-selection", 0, 0, window_copy_cmd_clear_selection }, - { "copy-end-of-line", 0, 0, + { "copy-end-of-line", 0, 1, window_copy_cmd_copy_end_of_line }, - { "copy-line", 0, 0, + { "copy-line", 0, 1, window_copy_cmd_copy_line }, - { "copy-pipe", 1, 1, + { "copy-pipe", 1, 2, window_copy_cmd_copy_pipe }, - { "copy-pipe-and-cancel", 1, 1, + { "copy-pipe-and-cancel", 1, 2, window_copy_cmd_copy_pipe_and_cancel }, - { "copy-selection", 0, 0, + { "copy-selection", 0, 1, window_copy_cmd_copy_selection }, - { "copy-selection-and-cancel", 0, 0, + { "copy-selection-and-cancel", 0, 1, window_copy_cmd_copy_selection_and_cancel }, { "cursor-down", 0, 0, window_copy_cmd_cursor_down }, @@ -1576,7 +1644,7 @@ static const struct { static void window_copy_command(struct window_mode_entry *wme, struct client *c, - struct session *s, __unused struct winlink *wl, struct args *args, + struct session *s, struct winlink *wl, struct args *args, struct mouse_event *m) { struct window_copy_mode_data *data = wme->data; @@ -1595,8 +1663,10 @@ window_copy_command(struct window_mode_entry *wme, struct client *c, cs.wme = wme; cs.args = args; cs.m = m; + cs.c = c; cs.s = s; + cs.wl = wl; action = WINDOW_COPY_CMD_NOTHING; for (i = 0; i < nitems(window_copy_cmd_table); i++) { @@ -2331,7 +2401,8 @@ window_copy_get_selection(struct window_mode_entry *wme, size_t *len) } static void -window_copy_copy_buffer(struct window_mode_entry *wme, void *buf, size_t len) +window_copy_copy_buffer(struct window_mode_entry *wme, const char *prefix, + void *buf, size_t len) { struct window_pane *wp = wme->wp; struct screen_write_ctx ctx; @@ -2343,41 +2414,35 @@ window_copy_copy_buffer(struct window_mode_entry *wme, void *buf, size_t len) notify_pane("pane-set-clipboard", wp); } - if (paste_set(buf, len, NULL, NULL) != 0) - free(buf); + paste_add(prefix, buf, len); } static void window_copy_copy_pipe(struct window_mode_entry *wme, struct session *s, - const char *fmt) + const char *prefix, const char *command) { - struct window_pane *wp = wme->wp; - void *buf; - size_t len; - struct job *job; - char *expanded; + void *buf; + size_t len; + struct job *job; buf = window_copy_get_selection(wme, &len); if (buf == NULL) return; - expanded = format_single(NULL, fmt, NULL, s, NULL, wp); - job = job_run(expanded, s, NULL, NULL, NULL, NULL, NULL, JOB_NOWAIT); + job = job_run(command, s, NULL, NULL, NULL, NULL, NULL, JOB_NOWAIT); bufferevent_write(job_get_event(job), buf, len); - - free(expanded); - window_copy_copy_buffer(wme, buf, len); + window_copy_copy_buffer(wme, prefix, buf, len); } static void -window_copy_copy_selection(struct window_mode_entry *wme) +window_copy_copy_selection(struct window_mode_entry *wme, const char *prefix) { char *buf; size_t len; buf = window_copy_get_selection(wme, &len); if (buf != NULL) - window_copy_copy_buffer(wme, buf, len); + window_copy_copy_buffer(wme, prefix, buf, len); } static void |