xref: /openbsd-src/usr.bin/tmux/paste.c (revision 416cec2412f5a60da99e0c977ce72713bb5d7de0)
1 /* $OpenBSD: paste.c,v 1.13 2012/09/04 13:24:50 nicm Exp $ */
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 
22 #include <stdlib.h>
23 #include <string.h>
24 #include <vis.h>
25 
26 #include "tmux.h"
27 
28 /*
29  * Stack of paste buffers. Note that paste buffer data is not necessarily a C
30  * string!
31  */
32 
33 /* Return each item of the stack in turn. */
34 struct paste_buffer *
35 paste_walk_stack(struct paste_stack *ps, u_int *idx)
36 {
37 	struct paste_buffer	*pb;
38 
39 	pb = paste_get_index(ps, *idx);
40 	(*idx)++;
41 	return (pb);
42 }
43 
44 /* Get the top item on the stack. */
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 
53 /* Get an item by its index. */
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 
62 /* Free the top item on the stack. */
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 
74 	free(pb->data);
75 	free(pb);
76 
77 	return (0);
78 }
79 
80 /* Free an item by index. */
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 
92 	free(pb->data);
93 	free(pb);
94 
95 	return (0);
96 }
97 
98 /*
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  */
102 void
103 paste_add(struct paste_stack *ps, char *data, size_t size, u_int limit)
104 {
105 	struct paste_buffer	*pb;
106 
107 	if (size == 0)
108 		return;
109 
110 	while (ARRAY_LENGTH(ps) >= limit) {
111 		pb = ARRAY_LAST(ps);
112 		free(pb->data);
113 		free(pb);
114 		ARRAY_TRUNC(ps, 1);
115 	}
116 
117 	pb = xmalloc(sizeof *pb);
118 	ARRAY_INSERT(ps, 0, pb);
119 
120 	pb->data = data;
121 	pb->size = size;
122 }
123 
124 
125 /*
126  * Replace an item on the stack. Note that the caller is responsible for
127  * allocating data.
128  */
129 int
130 paste_replace(struct paste_stack *ps, u_int idx, char *data, size_t size)
131 {
132 	struct paste_buffer	*pb;
133 
134 	if (size == 0)
135 		return (0);
136 
137 	if (idx >= ARRAY_LENGTH(ps))
138 		return (-1);
139 
140 	pb = ARRAY_ITEM(ps, idx);
141 	free(pb->data);
142 
143 	pb->data = data;
144 	pb->size = size;
145 
146 	return (0);
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);
165 	if (pb->size > width || used > width)
166 		strlcpy(buf + width - 3, "...", 4);
167 
168 	return (buf);
169 }
170