Merge branch 'obsd-master'

pull/1674/head
Thomas Adam 2019-04-02 11:02:44 +01:00
commit bfc1f0ca62
8 changed files with 178 additions and 80 deletions

69
grid.c
View File

@ -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;
u_int ax = 0, ay = 0, yy;
if (py > gd->hsize + gd->sy - 1) {
px = UINT_MAX;
py = gd->hsize + gd->sy - 1;
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;
}

View File

@ -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. */

View File

@ -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);
}

View File

@ -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) {

21
tmux.1
View File

@ -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

6
tmux.h
View File

@ -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 *);

View File

@ -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);
}

View File

@ -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 (s != NULL && *argument != '\0')
window_copy_copy_pipe(wme, s, argument);
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);
}
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 (s != NULL && *argument != '\0') {
window_copy_copy_pipe(wme, s, argument);
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);
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