Annotation of src/usr.bin/tmux/paste.c, Revision 1.14
1.14 ! nicm 1: /* $OpenBSD: paste.c,v 1.13 2012/09/04 13:24:50 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:
134: if (size == 0)
135: return (0);
1.1 nicm 136:
137: if (idx >= ARRAY_LENGTH(ps))
138: return (-1);
139:
140: pb = ARRAY_ITEM(ps, idx);
1.12 nicm 141: free(pb->data);
1.1 nicm 142:
143: pb->data = data;
1.4 nicm 144: pb->size = size;
1.1 nicm 145:
146: return (0);
1.9 nicm 147: }
148:
149: /* Convert a buffer into a visible string. */
150: char *
151: paste_print(struct paste_buffer *pb, size_t width)
152: {
153: char *buf;
154: size_t len, used;
155:
156: if (width < 3)
157: width = 3;
158: buf = xmalloc(width * 4 + 1);
159:
160: len = pb->size;
161: if (len > width)
162: len = width;
163:
164: used = strvisx(buf, pb->data, len, VIS_OCTAL|VIS_TAB|VIS_NL);
1.13 nicm 165: if (pb->size > width || used > width)
166: strlcpy(buf + width - 3, "...", 4);
1.9 nicm 167:
168: return (buf);
1.14 ! nicm 169: }
! 170:
! 171: /* Paste into a window pane, filtering '\n' according to separator. */
! 172: void
! 173: paste_send_pane (struct paste_buffer *pb, struct window_pane *wp,
! 174: const char *sep, int bracket)
! 175: {
! 176: const char *data = pb->data, *end = data + pb->size, *lf;
! 177: size_t seplen;
! 178:
! 179: if (bracket)
! 180: bufferevent_write(wp->event, "\033[200~", 6);
! 181:
! 182: seplen = strlen(sep);
! 183: while ((lf = memchr(data, '\n', end - data)) != NULL) {
! 184: if (lf != data)
! 185: bufferevent_write(wp->event, data, lf - data);
! 186: bufferevent_write(wp->event, sep, seplen);
! 187: data = lf + 1;
! 188: }
! 189:
! 190: if (end != data)
! 191: bufferevent_write(wp->event, data, end - data);
! 192:
! 193: if (bracket)
! 194: bufferevent_write(wp->event, "\033[201~", 6);
1.1 nicm 195: }