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