Annotation of src/usr.bin/tmux/cmd-paste-buffer.c, Revision 1.15
1.15 ! nicm 1: /* $OpenBSD: cmd-paste-buffer.c,v 1.14 2010/08/11 07:38:00 nicm Exp $ */
1.1 nicm 2:
3: /*
4: * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
5: *
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.
9: *
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.
17: */
18:
19: #include <sys/types.h>
20:
1.13 nicm 21: #include <stdlib.h>
1.1 nicm 22: #include <string.h>
1.13 nicm 23: #include <vis.h>
1.1 nicm 24:
25: #include "tmux.h"
26:
27: /*
28: * Paste paste buffer if present.
29: */
30:
1.13 nicm 31: struct cmd_paste_buffer_data {
32: char *target;
33: int buffer;
34:
35: int flag_delete;
36: char *sepstr;
37: };
38:
39: void cmd_paste_buffer_init(struct cmd *, int);
40: int cmd_paste_buffer_parse(struct cmd *, int, char **, char **);
1.1 nicm 41: int cmd_paste_buffer_exec(struct cmd *, struct cmd_ctx *);
1.13 nicm 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);
1.1 nicm 46:
47: const struct cmd_entry cmd_paste_buffer_entry = {
48: "paste-buffer", "pasteb",
1.14 nicm 49: "[-dr] [-s separator] [-b buffer-index] [-t target-pane]",
1.13 nicm 50: 0, "",
51: cmd_paste_buffer_init,
52: cmd_paste_buffer_parse,
1.1 nicm 53: cmd_paste_buffer_exec,
1.13 nicm 54: cmd_paste_buffer_free,
55: cmd_paste_buffer_print
1.1 nicm 56: };
57:
1.13 nicm 58: /* ARGSUSED */
59: void
60: cmd_paste_buffer_init(struct cmd *self, unused int arg)
61: {
62: struct cmd_paste_buffer_data *data;
63:
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");
69: }
70:
71: int
72: cmd_paste_buffer_parse(struct cmd *self, int argc, char **argv, char **cause)
73: {
74: struct cmd_paste_buffer_data *data;
75: int opt, n;
76: const char *errstr;
77:
78: cmd_paste_buffer_init(self, 0);
79: data = self->data;
80:
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;
89: }
90: data->buffer = n;
91: }
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;
112: }
113: }
114: argc -= optind;
115: argv += optind;
116:
117: return (0);
118:
119: usage:
120: xasprintf(cause, "usage: %s %s", self->entry->name, self->entry->usage);
121:
122: error:
123: self->entry->free(self);
124: return (-1);
125: }
126:
1.1 nicm 127: int
128: cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
129: {
1.13 nicm 130: struct cmd_paste_buffer_data *data = self->data;
131: struct window_pane *wp;
132: struct session *s;
133: struct paste_buffer *pb;
1.1 nicm 134:
1.12 nicm 135: if (cmd_find_pane(ctx, data->target, &s, &wp) == NULL)
1.1 nicm 136: return (-1);
137:
138: if (data->buffer == -1)
1.15 ! nicm 139: pb = paste_get_top(&global_buffers);
1.1 nicm 140: else {
1.15 ! nicm 141: pb = paste_get_index(&global_buffers, data->buffer);
! 142: if (pb == NULL) {
1.1 nicm 143: ctx->error(ctx, "no buffer %d", data->buffer);
144: return (-1);
145: }
146: }
147:
1.13 nicm 148: if (pb != NULL)
149: cmd_paste_buffer_filter(wp, pb->data, pb->size, data->sepstr);
1.1 nicm 150:
151: /* Delete the buffer if -d. */
1.13 nicm 152: if (data->flag_delete) {
1.1 nicm 153: if (data->buffer == -1)
1.15 ! nicm 154: paste_free_top(&global_buffers);
1.1 nicm 155: else
1.15 ! nicm 156: paste_free_index(&global_buffers, data->buffer);
1.1 nicm 157: }
158:
1.10 nicm 159: return (0);
1.3 nicm 160: }
161:
1.13 nicm 162: /* Add bytes to a buffer and filter '\n' according to separator. */
1.3 nicm 163: void
1.13 nicm 164: cmd_paste_buffer_filter(
165: struct window_pane *wp, const char *data, size_t size, char *sep)
1.3 nicm 166: {
167: const char *end = data + size;
168: const char *lf;
1.13 nicm 169: size_t seplen;
1.3 nicm 170:
1.13 nicm 171: seplen = strlen(sep);
1.3 nicm 172: while ((lf = memchr(data, '\n', end - data)) != NULL) {
173: if (lf != data)
1.7 nicm 174: bufferevent_write(wp->event, data, lf - data);
1.13 nicm 175: bufferevent_write(wp->event, sep, seplen);
1.3 nicm 176: data = lf + 1;
177: }
178:
179: if (end != data)
1.7 nicm 180: bufferevent_write(wp->event, data, end - data);
1.13 nicm 181: }
182:
183: void
184: cmd_paste_buffer_free(struct cmd *self)
185: {
186: struct cmd_paste_buffer_data *data = self->data;
187:
188: if (data->target != NULL)
189: xfree(data->target);
190: if (data->sepstr != NULL)
191: xfree(data->sepstr);
192: xfree(data);
193: }
194:
195: size_t
196: cmd_paste_buffer_print(struct cmd *self, char *buf, size_t len)
197: {
198: struct cmd_paste_buffer_data *data = self->data;
199: size_t off = 0;
200: char tmp[BUFSIZ];
201: int r_flag;
202:
203: r_flag = 0;
204: if (data->sepstr != NULL)
205: r_flag = (data->sepstr[0] == '\n' && data->sepstr[1] == '\0');
206:
207: off += xsnprintf(buf, len, "%s", self->entry->name);
208: if (data == NULL)
209: return (off);
210: if (off < len && data->flag_delete)
211: off += xsnprintf(buf + off, len - off, " -d");
212: if (off < len && r_flag)
213: off += xsnprintf(buf + off, len - off, " -r");
214: if (off < len && data->buffer != -1)
215: off += xsnprintf(buf + off, len - off, " -b %d", data->buffer);
216: if (off < len && data->sepstr != NULL && !r_flag) {
217: strnvis(
218: tmp, data->sepstr, sizeof tmp, VIS_OCTAL|VIS_TAB|VIS_NL);
219: off += cmd_prarg(buf + off, len - off, " -s ", tmp);
220: }
221: if (off < len && data->target != NULL)
222: off += cmd_prarg(buf + off, len - off, " -t ", data->target);
223: return (off);
1.1 nicm 224: }