Annotation of src/usr.bin/tmux/cmd-paste-buffer.c, Revision 1.14
1.14 ! nicm 1: /* $OpenBSD: cmd-paste-buffer.c,v 1.13 2010/05/19 22:28:14 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)
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);
144: }
145: }
146:
1.13 nicm 147: if (pb != NULL)
148: cmd_paste_buffer_filter(wp, pb->data, pb->size, data->sepstr);
1.1 nicm 149:
150: /* Delete the buffer if -d. */
1.13 nicm 151: if (data->flag_delete) {
1.1 nicm 152: if (data->buffer == -1)
153: paste_free_top(&s->buffers);
154: else
155: paste_free_index(&s->buffers, data->buffer);
156: }
157:
1.10 nicm 158: return (0);
1.3 nicm 159: }
160:
1.13 nicm 161: /* Add bytes to a buffer and filter '\n' according to separator. */
1.3 nicm 162: void
1.13 nicm 163: cmd_paste_buffer_filter(
164: struct window_pane *wp, const char *data, size_t size, char *sep)
1.3 nicm 165: {
166: const char *end = data + size;
167: const char *lf;
1.13 nicm 168: size_t seplen;
1.3 nicm 169:
1.13 nicm 170: seplen = strlen(sep);
1.3 nicm 171: while ((lf = memchr(data, '\n', end - data)) != NULL) {
172: if (lf != data)
1.7 nicm 173: bufferevent_write(wp->event, data, lf - data);
1.13 nicm 174: bufferevent_write(wp->event, sep, seplen);
1.3 nicm 175: data = lf + 1;
176: }
177:
178: if (end != data)
1.7 nicm 179: bufferevent_write(wp->event, data, end - data);
1.13 nicm 180: }
181:
182: void
183: cmd_paste_buffer_free(struct cmd *self)
184: {
185: struct cmd_paste_buffer_data *data = self->data;
186:
187: if (data->target != NULL)
188: xfree(data->target);
189: if (data->sepstr != NULL)
190: xfree(data->sepstr);
191: xfree(data);
192: }
193:
194: size_t
195: cmd_paste_buffer_print(struct cmd *self, char *buf, size_t len)
196: {
197: struct cmd_paste_buffer_data *data = self->data;
198: size_t off = 0;
199: char tmp[BUFSIZ];
200: int r_flag;
201:
202: r_flag = 0;
203: if (data->sepstr != NULL)
204: r_flag = (data->sepstr[0] == '\n' && data->sepstr[1] == '\0');
205:
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);
219: }
220: if (off < len && data->target != NULL)
221: off += cmd_prarg(buf + off, len - off, " -t ", data->target);
222: return (off);
1.1 nicm 223: }