xref: /openbsd-src/usr.bin/tmux/paste.c (revision 50027fe110c3c362514cbbf1128910104a00203e)
1 /* $OpenBSD: paste.c,v 1.8 2009/12/03 22:50:10 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 <string.h>
23 
24 #include "tmux.h"
25 
26 /*
27  * Stack of paste buffers. Note that paste buffer data is not necessarily a C
28  * string!
29  */
30 
31 void
32 paste_init_stack(struct paste_stack *ps)
33 {
34 	ARRAY_INIT(ps);
35 }
36 
37 void
38 paste_free_stack(struct paste_stack *ps)
39 {
40 	while (paste_free_top(ps) == 0)
41 		;
42 }
43 
44 /* Return each item of the stack in turn. */
45 struct paste_buffer *
46 paste_walk_stack(struct paste_stack *ps, uint *idx)
47 {
48 	struct paste_buffer	*pb;
49 
50 	pb = paste_get_index(ps, *idx);
51 	(*idx)++;
52 	return (pb);
53 }
54 
55 /* Get the top item on the stack. */
56 struct paste_buffer *
57 paste_get_top(struct paste_stack *ps)
58 {
59 	if (ARRAY_LENGTH(ps) == 0)
60 		return (NULL);
61 	return (ARRAY_FIRST(ps));
62 }
63 
64 /* Get an item by its index. */
65 struct paste_buffer *
66 paste_get_index(struct paste_stack *ps, u_int idx)
67 {
68 	if (idx >= ARRAY_LENGTH(ps))
69 		return (NULL);
70 	return (ARRAY_ITEM(ps, idx));
71 }
72 
73 /* Free the top item on the stack. */
74 int
75 paste_free_top(struct paste_stack *ps)
76 {
77 	struct paste_buffer	*pb;
78 
79 	if (ARRAY_LENGTH(ps) == 0)
80 		return (-1);
81 
82 	pb = ARRAY_FIRST(ps);
83 	ARRAY_REMOVE(ps, 0);
84 
85 	xfree(pb->data);
86 	xfree(pb);
87 
88 	return (0);
89 }
90 
91 /* Free an item by index. */
92 int
93 paste_free_index(struct paste_stack *ps, u_int idx)
94 {
95 	struct paste_buffer	*pb;
96 
97 	if (idx >= ARRAY_LENGTH(ps))
98 		return (-1);
99 
100 	pb = ARRAY_ITEM(ps, idx);
101 	ARRAY_REMOVE(ps, idx);
102 
103 	xfree(pb->data);
104 	xfree(pb);
105 
106 	return (0);
107 }
108 
109 /*
110  * Add an item onto the top of the stack, freeing the bottom if at limit. Note
111  * that the caller is responsible for allocating data.
112  */
113 void
114 paste_add(struct paste_stack *ps, char *data, size_t size, u_int limit)
115 {
116 	struct paste_buffer	*pb;
117 
118 	if (size == 0)
119 		return;
120 
121 	while (ARRAY_LENGTH(ps) >= limit) {
122 		pb = ARRAY_LAST(ps);
123 		xfree(pb->data);
124 		xfree(pb);
125 		ARRAY_TRUNC(ps, 1);
126 	}
127 
128 	pb = xmalloc(sizeof *pb);
129 	ARRAY_INSERT(ps, 0, pb);
130 
131 	pb->data = data;
132 	pb->size = size;
133 }
134 
135 
136 /*
137  * Replace an item on the stack. Note that the caller is responsible for
138  * allocating data.
139  */
140 int
141 paste_replace(struct paste_stack *ps, u_int idx, char *data, size_t size)
142 {
143 	struct paste_buffer	*pb;
144 
145 	if (size == 0)
146 		return (0);
147 
148 	if (idx >= ARRAY_LENGTH(ps))
149 		return (-1);
150 
151 	pb = ARRAY_ITEM(ps, idx);
152 	xfree(pb->data);
153 
154 	pb->data = data;
155 	pb->size = size;
156 
157 	return (0);
158 }
159