xref: /minix3/external/bsd/tmux/dist/paste.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1*0a6a1f1dSLionel Sambuc /* Id */
2eda6f593SDavid van Moolenbroek 
3eda6f593SDavid van Moolenbroek /*
4eda6f593SDavid van Moolenbroek  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
5eda6f593SDavid van Moolenbroek  *
6eda6f593SDavid van Moolenbroek  * Permission to use, copy, modify, and distribute this software for any
7eda6f593SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
8eda6f593SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
9eda6f593SDavid van Moolenbroek  *
10eda6f593SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11eda6f593SDavid van Moolenbroek  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12eda6f593SDavid van Moolenbroek  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13eda6f593SDavid van Moolenbroek  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14eda6f593SDavid van Moolenbroek  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15eda6f593SDavid van Moolenbroek  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16eda6f593SDavid van Moolenbroek  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17eda6f593SDavid van Moolenbroek  */
18eda6f593SDavid van Moolenbroek 
19eda6f593SDavid van Moolenbroek #include <sys/types.h>
20eda6f593SDavid van Moolenbroek #include <sys/time.h>
21eda6f593SDavid van Moolenbroek 
22*0a6a1f1dSLionel Sambuc #include <stdlib.h>
23eda6f593SDavid van Moolenbroek #include <string.h>
24eda6f593SDavid van Moolenbroek 
25eda6f593SDavid van Moolenbroek #include "tmux.h"
26eda6f593SDavid van Moolenbroek 
27eda6f593SDavid van Moolenbroek /*
28eda6f593SDavid van Moolenbroek  * Stack of paste buffers. Note that paste buffer data is not necessarily a C
29eda6f593SDavid van Moolenbroek  * string!
30eda6f593SDavid van Moolenbroek  */
31eda6f593SDavid van Moolenbroek 
32eda6f593SDavid van Moolenbroek /* Return each item of the stack in turn. */
33eda6f593SDavid van Moolenbroek struct paste_buffer *
paste_walk_stack(struct paste_stack * ps,u_int * idx)34eda6f593SDavid van Moolenbroek paste_walk_stack(struct paste_stack *ps, u_int *idx)
35eda6f593SDavid van Moolenbroek {
36eda6f593SDavid van Moolenbroek 	struct paste_buffer	*pb;
37eda6f593SDavid van Moolenbroek 
38eda6f593SDavid van Moolenbroek 	pb = paste_get_index(ps, *idx);
39eda6f593SDavid van Moolenbroek 	(*idx)++;
40eda6f593SDavid van Moolenbroek 	return (pb);
41eda6f593SDavid van Moolenbroek }
42eda6f593SDavid van Moolenbroek 
43eda6f593SDavid van Moolenbroek /* Get the top item on the stack. */
44eda6f593SDavid van Moolenbroek struct paste_buffer *
paste_get_top(struct paste_stack * ps)45eda6f593SDavid van Moolenbroek paste_get_top(struct paste_stack *ps)
46eda6f593SDavid van Moolenbroek {
47eda6f593SDavid van Moolenbroek 	if (ARRAY_LENGTH(ps) == 0)
48eda6f593SDavid van Moolenbroek 		return (NULL);
49eda6f593SDavid van Moolenbroek 	return (ARRAY_FIRST(ps));
50eda6f593SDavid van Moolenbroek }
51eda6f593SDavid van Moolenbroek 
52eda6f593SDavid van Moolenbroek /* Get an item by its index. */
53eda6f593SDavid van Moolenbroek struct paste_buffer *
paste_get_index(struct paste_stack * ps,u_int idx)54eda6f593SDavid van Moolenbroek paste_get_index(struct paste_stack *ps, u_int idx)
55eda6f593SDavid van Moolenbroek {
56eda6f593SDavid van Moolenbroek 	if (idx >= ARRAY_LENGTH(ps))
57eda6f593SDavid van Moolenbroek 		return (NULL);
58eda6f593SDavid van Moolenbroek 	return (ARRAY_ITEM(ps, idx));
59eda6f593SDavid van Moolenbroek }
60eda6f593SDavid van Moolenbroek 
61eda6f593SDavid van Moolenbroek /* Free the top item on the stack. */
62eda6f593SDavid van Moolenbroek int
paste_free_top(struct paste_stack * ps)63eda6f593SDavid van Moolenbroek paste_free_top(struct paste_stack *ps)
64eda6f593SDavid van Moolenbroek {
65eda6f593SDavid van Moolenbroek 	struct paste_buffer	*pb;
66eda6f593SDavid van Moolenbroek 
67eda6f593SDavid van Moolenbroek 	if (ARRAY_LENGTH(ps) == 0)
68eda6f593SDavid van Moolenbroek 		return (-1);
69eda6f593SDavid van Moolenbroek 
70eda6f593SDavid van Moolenbroek 	pb = ARRAY_FIRST(ps);
71eda6f593SDavid van Moolenbroek 	ARRAY_REMOVE(ps, 0);
72eda6f593SDavid van Moolenbroek 
73*0a6a1f1dSLionel Sambuc 	free(pb->data);
74*0a6a1f1dSLionel Sambuc 	free(pb);
75eda6f593SDavid van Moolenbroek 
76eda6f593SDavid van Moolenbroek 	return (0);
77eda6f593SDavid van Moolenbroek }
78eda6f593SDavid van Moolenbroek 
79eda6f593SDavid van Moolenbroek /* Free an item by index. */
80eda6f593SDavid van Moolenbroek int
paste_free_index(struct paste_stack * ps,u_int idx)81eda6f593SDavid van Moolenbroek paste_free_index(struct paste_stack *ps, u_int idx)
82eda6f593SDavid van Moolenbroek {
83eda6f593SDavid van Moolenbroek 	struct paste_buffer	*pb;
84eda6f593SDavid van Moolenbroek 
85eda6f593SDavid van Moolenbroek 	if (idx >= ARRAY_LENGTH(ps))
86eda6f593SDavid van Moolenbroek 		return (-1);
87eda6f593SDavid van Moolenbroek 
88eda6f593SDavid van Moolenbroek 	pb = ARRAY_ITEM(ps, idx);
89eda6f593SDavid van Moolenbroek 	ARRAY_REMOVE(ps, idx);
90eda6f593SDavid van Moolenbroek 
91*0a6a1f1dSLionel Sambuc 	free(pb->data);
92*0a6a1f1dSLionel Sambuc 	free(pb);
93eda6f593SDavid van Moolenbroek 
94eda6f593SDavid van Moolenbroek 	return (0);
95eda6f593SDavid van Moolenbroek }
96eda6f593SDavid van Moolenbroek 
97eda6f593SDavid van Moolenbroek /*
98eda6f593SDavid van Moolenbroek  * Add an item onto the top of the stack, freeing the bottom if at limit. Note
99eda6f593SDavid van Moolenbroek  * that the caller is responsible for allocating data.
100eda6f593SDavid van Moolenbroek  */
101eda6f593SDavid van Moolenbroek void
paste_add(struct paste_stack * ps,char * data,size_t size,u_int limit)102eda6f593SDavid van Moolenbroek paste_add(struct paste_stack *ps, char *data, size_t size, u_int limit)
103eda6f593SDavid van Moolenbroek {
104eda6f593SDavid van Moolenbroek 	struct paste_buffer	*pb;
105eda6f593SDavid van Moolenbroek 
106eda6f593SDavid van Moolenbroek 	if (size == 0)
107eda6f593SDavid van Moolenbroek 		return;
108eda6f593SDavid van Moolenbroek 
109eda6f593SDavid van Moolenbroek 	while (ARRAY_LENGTH(ps) >= limit) {
110eda6f593SDavid van Moolenbroek 		pb = ARRAY_LAST(ps);
111*0a6a1f1dSLionel Sambuc 		free(pb->data);
112*0a6a1f1dSLionel Sambuc 		free(pb);
113eda6f593SDavid van Moolenbroek 		ARRAY_TRUNC(ps, 1);
114eda6f593SDavid van Moolenbroek 	}
115eda6f593SDavid van Moolenbroek 
116eda6f593SDavid van Moolenbroek 	pb = xmalloc(sizeof *pb);
117eda6f593SDavid van Moolenbroek 	ARRAY_INSERT(ps, 0, pb);
118eda6f593SDavid van Moolenbroek 
119eda6f593SDavid van Moolenbroek 	pb->data = data;
120eda6f593SDavid van Moolenbroek 	pb->size = size;
121eda6f593SDavid van Moolenbroek }
122eda6f593SDavid van Moolenbroek 
123eda6f593SDavid van Moolenbroek 
124eda6f593SDavid van Moolenbroek /*
125eda6f593SDavid van Moolenbroek  * Replace an item on the stack. Note that the caller is responsible for
126eda6f593SDavid van Moolenbroek  * allocating data.
127eda6f593SDavid van Moolenbroek  */
128eda6f593SDavid van Moolenbroek int
paste_replace(struct paste_stack * ps,u_int idx,char * data,size_t size)129eda6f593SDavid van Moolenbroek paste_replace(struct paste_stack *ps, u_int idx, char *data, size_t size)
130eda6f593SDavid van Moolenbroek {
131eda6f593SDavid van Moolenbroek 	struct paste_buffer	*pb;
132eda6f593SDavid van Moolenbroek 
133*0a6a1f1dSLionel Sambuc 	if (size == 0) {
134*0a6a1f1dSLionel Sambuc 		free(data);
135eda6f593SDavid van Moolenbroek 		return (0);
136*0a6a1f1dSLionel Sambuc 	}
137eda6f593SDavid van Moolenbroek 
138eda6f593SDavid van Moolenbroek 	if (idx >= ARRAY_LENGTH(ps))
139eda6f593SDavid van Moolenbroek 		return (-1);
140eda6f593SDavid van Moolenbroek 
141eda6f593SDavid van Moolenbroek 	pb = ARRAY_ITEM(ps, idx);
142*0a6a1f1dSLionel Sambuc 	free(pb->data);
143eda6f593SDavid van Moolenbroek 
144eda6f593SDavid van Moolenbroek 	pb->data = data;
145eda6f593SDavid van Moolenbroek 	pb->size = size;
146eda6f593SDavid van Moolenbroek 
147eda6f593SDavid van Moolenbroek 	return (0);
148eda6f593SDavid van Moolenbroek }
149eda6f593SDavid van Moolenbroek 
150eda6f593SDavid van Moolenbroek /* Convert a buffer into a visible string. */
151eda6f593SDavid van Moolenbroek char *
paste_print(struct paste_buffer * pb,size_t width)152eda6f593SDavid van Moolenbroek paste_print(struct paste_buffer *pb, size_t width)
153eda6f593SDavid van Moolenbroek {
154eda6f593SDavid van Moolenbroek 	char	*buf;
155eda6f593SDavid van Moolenbroek 	size_t	 len, used;
156eda6f593SDavid van Moolenbroek 
157eda6f593SDavid van Moolenbroek 	if (width < 3)
158eda6f593SDavid van Moolenbroek 		width = 3;
159eda6f593SDavid van Moolenbroek 	buf = xmalloc(width * 4 + 1);
160eda6f593SDavid van Moolenbroek 
161eda6f593SDavid van Moolenbroek 	len = pb->size;
162eda6f593SDavid van Moolenbroek 	if (len > width)
163eda6f593SDavid van Moolenbroek 		len = width;
164eda6f593SDavid van Moolenbroek 
165eda6f593SDavid van Moolenbroek 	used = strvisx(buf, pb->data, len, VIS_OCTAL|VIS_TAB|VIS_NL);
166*0a6a1f1dSLionel Sambuc 	if (pb->size > width || used > width)
167*0a6a1f1dSLionel Sambuc 		strlcpy(buf + width - 3, "...", 4);
168eda6f593SDavid van Moolenbroek 
169eda6f593SDavid van Moolenbroek 	return (buf);
170eda6f593SDavid van Moolenbroek }
171*0a6a1f1dSLionel Sambuc 
172*0a6a1f1dSLionel Sambuc /* Paste into a window pane, filtering '\n' according to separator. */
173*0a6a1f1dSLionel Sambuc void
paste_send_pane(struct paste_buffer * pb,struct window_pane * wp,const char * sep,int bracket)174*0a6a1f1dSLionel Sambuc paste_send_pane (struct paste_buffer *pb, struct window_pane *wp,
175*0a6a1f1dSLionel Sambuc     const char *sep, int bracket)
176*0a6a1f1dSLionel Sambuc {
177*0a6a1f1dSLionel Sambuc 	const char	*data = pb->data, *end = data + pb->size, *lf;
178*0a6a1f1dSLionel Sambuc 	size_t		 seplen;
179*0a6a1f1dSLionel Sambuc 
180*0a6a1f1dSLionel Sambuc 	if (bracket)
181*0a6a1f1dSLionel Sambuc 		bufferevent_write(wp->event, "\033[200~", 6);
182*0a6a1f1dSLionel Sambuc 
183*0a6a1f1dSLionel Sambuc 	seplen = strlen(sep);
184*0a6a1f1dSLionel Sambuc 	while ((lf = memchr(data, '\n', end - data)) != NULL) {
185*0a6a1f1dSLionel Sambuc 		if (lf != data)
186*0a6a1f1dSLionel Sambuc 			bufferevent_write(wp->event, data, lf - data);
187*0a6a1f1dSLionel Sambuc 		bufferevent_write(wp->event, sep, seplen);
188*0a6a1f1dSLionel Sambuc 		data = lf + 1;
189*0a6a1f1dSLionel Sambuc 	}
190*0a6a1f1dSLionel Sambuc 
191*0a6a1f1dSLionel Sambuc 	if (end != data)
192*0a6a1f1dSLionel Sambuc 		bufferevent_write(wp->event, data, end - data);
193*0a6a1f1dSLionel Sambuc 
194*0a6a1f1dSLionel Sambuc 	if (bracket)
195*0a6a1f1dSLionel Sambuc 		bufferevent_write(wp->event, "\033[201~", 6);
196*0a6a1f1dSLionel Sambuc }
197