Annotation of src/usr.bin/tmux/paste.c, Revision 1.18
1.18 ! nicm 1: /* $OpenBSD: paste.c,v 1.17 2014/04/02 18:12:18 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: #include <sys/time.h>
21:
1.12 nicm 22: #include <stdlib.h>
1.1 nicm 23: #include <string.h>
1.9 nicm 24: #include <vis.h>
1.1 nicm 25:
26: #include "tmux.h"
27:
1.7 nicm 28: /*
29: * Stack of paste buffers. Note that paste buffer data is not necessarily a C
30: * string!
31: */
1.1 nicm 32:
1.18 ! nicm 33: ARRAY_DECL(, struct paste_buffer *) paste_buffers = ARRAY_INITIALIZER;
! 34:
1.7 nicm 35: /* Return each item of the stack in turn. */
1.1 nicm 36: struct paste_buffer *
1.18 ! nicm 37: paste_walk_stack(u_int *idx)
1.1 nicm 38: {
39: struct paste_buffer *pb;
40:
1.18 ! nicm 41: pb = paste_get_index(*idx);
1.1 nicm 42: (*idx)++;
43: return (pb);
44: }
45:
1.7 nicm 46: /* Get the top item on the stack. */
1.1 nicm 47: struct paste_buffer *
1.18 ! nicm 48: paste_get_top(void)
1.1 nicm 49: {
1.18 ! nicm 50: if (ARRAY_LENGTH(&paste_buffers) == 0)
1.1 nicm 51: return (NULL);
1.18 ! nicm 52: return (ARRAY_FIRST(&paste_buffers));
1.1 nicm 53: }
54:
1.7 nicm 55: /* Get an item by its index. */
1.1 nicm 56: struct paste_buffer *
1.18 ! nicm 57: paste_get_index(u_int idx)
1.1 nicm 58: {
1.18 ! nicm 59: if (idx >= ARRAY_LENGTH(&paste_buffers))
1.1 nicm 60: return (NULL);
1.18 ! nicm 61: return (ARRAY_ITEM(&paste_buffers, idx));
1.1 nicm 62: }
63:
1.7 nicm 64: /* Free the top item on the stack. */
1.1 nicm 65: int
1.18 ! nicm 66: paste_free_top(void)
1.1 nicm 67: {
68: struct paste_buffer *pb;
69:
1.18 ! nicm 70: if (ARRAY_LENGTH(&paste_buffers) == 0)
1.1 nicm 71: return (-1);
72:
1.18 ! nicm 73: pb = ARRAY_FIRST(&paste_buffers);
! 74: ARRAY_REMOVE(&paste_buffers, 0);
1.1 nicm 75:
1.12 nicm 76: free(pb->data);
77: free(pb);
1.1 nicm 78:
79: return (0);
80: }
81:
1.7 nicm 82: /* Free an item by index. */
1.1 nicm 83: int
1.18 ! nicm 84: paste_free_index(u_int idx)
1.1 nicm 85: {
86: struct paste_buffer *pb;
87:
1.18 ! nicm 88: if (idx >= ARRAY_LENGTH(&paste_buffers))
1.1 nicm 89: return (-1);
90:
1.18 ! nicm 91: pb = ARRAY_ITEM(&paste_buffers, idx);
! 92: ARRAY_REMOVE(&paste_buffers, idx);
1.1 nicm 93:
1.12 nicm 94: free(pb->data);
95: free(pb);
1.1 nicm 96:
97: return (0);
98: }
99:
1.8 nicm 100: /*
1.7 nicm 101: * Add an item onto the top of the stack, freeing the bottom if at limit. Note
102: * that the caller is responsible for allocating data.
103: */
1.1 nicm 104: void
1.18 ! nicm 105: paste_add(char *data, size_t size, u_int limit)
1.1 nicm 106: {
107: struct paste_buffer *pb;
1.2 nicm 108:
1.7 nicm 109: if (size == 0)
1.2 nicm 110: return;
1.1 nicm 111:
1.18 ! nicm 112: while (ARRAY_LENGTH(&paste_buffers) >= limit) {
! 113: pb = ARRAY_LAST(&paste_buffers);
1.12 nicm 114: free(pb->data);
115: free(pb);
1.18 ! nicm 116: ARRAY_TRUNC(&paste_buffers, 1);
1.3 nicm 117: }
1.1 nicm 118:
119: pb = xmalloc(sizeof *pb);
1.18 ! nicm 120: ARRAY_INSERT(&paste_buffers, 0, pb);
1.1 nicm 121:
122: pb->data = data;
1.4 nicm 123: pb->size = size;
1.1 nicm 124: }
125:
1.7 nicm 126:
1.8 nicm 127: /*
1.7 nicm 128: * Replace an item on the stack. Note that the caller is responsible for
129: * allocating data.
130: */
1.1 nicm 131: int
1.18 ! nicm 132: paste_replace(u_int idx, char *data, size_t size)
1.1 nicm 133: {
134: struct paste_buffer *pb;
1.7 nicm 135:
1.15 nicm 136: if (size == 0) {
137: free(data);
1.7 nicm 138: return (0);
1.15 nicm 139: }
1.1 nicm 140:
1.18 ! nicm 141: if (idx >= ARRAY_LENGTH(&paste_buffers))
1.1 nicm 142: return (-1);
143:
1.18 ! nicm 144: pb = ARRAY_ITEM(&paste_buffers, idx);
1.12 nicm 145: free(pb->data);
1.1 nicm 146:
147: pb->data = data;
1.4 nicm 148: pb->size = size;
1.1 nicm 149:
150: return (0);
1.9 nicm 151: }
152:
1.17 nicm 153: /* Convert start of buffer into a nice string. */
1.9 nicm 154: char *
1.17 nicm 155: paste_make_sample(struct paste_buffer *pb, int utf8flag)
1.9 nicm 156: {
1.17 nicm 157: char *buf;
158: size_t len, used;
159: const int flags = VIS_OCTAL|VIS_TAB|VIS_NL;
160: const size_t width = 200;
1.9 nicm 161:
162: len = pb->size;
163: if (len > width)
164: len = width;
1.17 nicm 165: buf = xmalloc(len * 4 + 4);
1.9 nicm 166:
1.17 nicm 167: if (utf8flag)
168: used = utf8_strvis(buf, pb->data, len, flags);
169: else
170: used = strvisx(buf, pb->data, len, flags);
1.13 nicm 171: if (pb->size > width || used > width)
1.17 nicm 172: strlcpy(buf + width, "...", 4);
1.9 nicm 173: return (buf);
1.14 nicm 174: }
175:
176: /* Paste into a window pane, filtering '\n' according to separator. */
177: void
1.16 nicm 178: paste_send_pane(struct paste_buffer *pb, struct window_pane *wp,
1.14 nicm 179: const char *sep, int bracket)
180: {
181: const char *data = pb->data, *end = data + pb->size, *lf;
182: size_t seplen;
183:
184: if (bracket)
185: bufferevent_write(wp->event, "\033[200~", 6);
186:
187: seplen = strlen(sep);
188: while ((lf = memchr(data, '\n', end - data)) != NULL) {
189: if (lf != data)
190: bufferevent_write(wp->event, data, lf - data);
191: bufferevent_write(wp->event, sep, seplen);
192: data = lf + 1;
193: }
194:
195: if (end != data)
196: bufferevent_write(wp->event, data, end - data);
197:
198: if (bracket)
199: bufferevent_write(wp->event, "\033[201~", 6);
1.1 nicm 200: }