When the mode-mouse option is on, support dragging to make a selection
[tmux-openbsd.git] / cmd-paste-buffer.c
blob0b9b39267340fd90929c9095ae733387927261ec
1 /* $OpenBSD$ */
3 /*
4 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/types.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <vis.h>
25 #include "tmux.h"
28 * Paste paste buffer if present.
31 struct cmd_paste_buffer_data {
32 char *target;
33 int buffer;
35 int flag_delete;
36 char *sepstr;
39 void cmd_paste_buffer_init(struct cmd *, int);
40 int cmd_paste_buffer_parse(struct cmd *, int, char **, char **);
41 int cmd_paste_buffer_exec(struct cmd *, struct cmd_ctx *);
42 void cmd_paste_buffer_filter(
43 struct window_pane *, const char *, size_t, char *);
44 void cmd_paste_buffer_free(struct cmd *);
45 size_t cmd_paste_buffer_print(struct cmd *, char *, size_t);
47 const struct cmd_entry cmd_paste_buffer_entry = {
48 "paste-buffer", "pasteb",
49 "[-dr] [-s separator] [-b buffer-index] [-t target-window]",
50 0, "",
51 cmd_paste_buffer_init,
52 cmd_paste_buffer_parse,
53 cmd_paste_buffer_exec,
54 cmd_paste_buffer_free,
55 cmd_paste_buffer_print
58 /* ARGSUSED */
59 void
60 cmd_paste_buffer_init(struct cmd *self, unused int arg)
62 struct cmd_paste_buffer_data *data;
64 self->data = data = xmalloc(sizeof *data);
65 data->target = NULL;
66 data->buffer = -1;
67 data->flag_delete = 0;
68 data->sepstr = xstrdup("\r");
71 int
72 cmd_paste_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
74 struct cmd_paste_buffer_data *data;
75 int opt, n;
76 const char *errstr;
78 cmd_paste_buffer_init(self, 0);
79 data = self->data;
81 while ((opt = getopt(argc, argv, "b:ds:t:r")) != -1) {
82 switch (opt) {
83 case 'b':
84 if (data->buffer == -1) {
85 n = strtonum(optarg, 0, INT_MAX, &errstr);
86 if (errstr != NULL) {
87 xasprintf(cause, "buffer %s", errstr);
88 goto error;
90 data->buffer = n;
92 break;
93 case 'd':
94 data->flag_delete = 1;
95 break;
96 case 's':
97 if (data->sepstr != NULL)
98 xfree(data->sepstr);
99 data->sepstr = xstrdup(optarg);
100 break;
101 case 't':
102 if (data->target == NULL)
103 data->target = xstrdup(optarg);
104 break;
105 case 'r':
106 if (data->sepstr != NULL)
107 xfree(data->sepstr);
108 data->sepstr = xstrdup("\n");
109 break;
110 default:
111 goto usage;
114 argc -= optind;
115 argv += optind;
117 return (0);
119 usage:
120 xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
122 error:
123 self->entry->free(self);
124 return (-1);
128 cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
130 struct cmd_paste_buffer_data *data = self->data;
131 struct window_pane *wp;
132 struct session *s;
133 struct paste_buffer *pb;
135 if (cmd_find_pane(ctx, data->target, &s, &wp) == NULL)
136 return (-1);
138 if (data->buffer == -1)
139 pb = paste_get_top(&s->buffers);
140 else {
141 if ((pb = paste_get_index(&s->buffers, data->buffer)) == NULL) {
142 ctx->error(ctx, "no buffer %d", data->buffer);
143 return (-1);
147 if (pb != NULL)
148 cmd_paste_buffer_filter(wp, pb->data, pb->size, data->sepstr);
150 /* Delete the buffer if -d. */
151 if (data->flag_delete) {
152 if (data->buffer == -1)
153 paste_free_top(&s->buffers);
154 else
155 paste_free_index(&s->buffers, data->buffer);
158 return (0);
161 /* Add bytes to a buffer and filter '\n' according to separator. */
162 void
163 cmd_paste_buffer_filter(
164 struct window_pane *wp, const char *data, size_t size, char *sep)
166 const char *end = data + size;
167 const char *lf;
168 size_t seplen;
170 seplen = strlen(sep);
171 while ((lf = memchr(data, '\n', end - data)) != NULL) {
172 if (lf != data)
173 bufferevent_write(wp->event, data, lf - data);
174 bufferevent_write(wp->event, sep, seplen);
175 data = lf + 1;
178 if (end != data)
179 bufferevent_write(wp->event, data, end - data);
182 void
183 cmd_paste_buffer_free(struct cmd *self)
185 struct cmd_paste_buffer_data *data = self->data;
187 if (data->target != NULL)
188 xfree(data->target);
189 if (data->sepstr != NULL)
190 xfree(data->sepstr);
191 xfree(data);
194 size_t
195 cmd_paste_buffer_print(struct cmd *self, char *buf, size_t len)
197 struct cmd_paste_buffer_data *data = self->data;
198 size_t off = 0;
199 char tmp[BUFSIZ];
200 int r_flag;
202 r_flag = 0;
203 if (data->sepstr != NULL)
204 r_flag = (data->sepstr[0] == '\n' && data->sepstr[1] == '\0');
206 off += xsnprintf(buf, len, "%s", self->entry->name);
207 if (data == NULL)
208 return (off);
209 if (off < len && data->flag_delete)
210 off += xsnprintf(buf + off, len - off, " -d");
211 if (off < len && r_flag)
212 off += xsnprintf(buf + off, len - off, " -r");
213 if (off < len && data->buffer != -1)
214 off += xsnprintf(buf + off, len - off, " -b %d", data->buffer);
215 if (off < len && data->sepstr != NULL && !r_flag) {
216 strnvis(
217 tmp, data->sepstr, sizeof tmp, VIS_OCTAL|VIS_TAB|VIS_NL);
218 off += cmd_prarg(buf + off, len - off, " -s ", tmp);
220 if (off < len && data->target != NULL)
221 off += cmd_prarg(buf + off, len - off, " -t ", data->target);
222 return (off);