tmux  3.2a
About: tmux is a terminal multiplexer that lets you switch easily between several programs in one terminal.
  Fossies Dox: tmux-3.2a.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

paste.c
Go to the documentation of this file.
1 /* $OpenBSD$ */
2 
3 /*
4  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
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 
21 #include <stdlib.h>
22 #include <string.h>
23 #include <time.h>
24 
25 #include "tmux.h"
26 
27 /*
28  * Set of paste buffers. Note that paste buffer data is not necessarily a C
29  * string!
30  */
31 
32 struct paste_buffer {
33  char *data;
34  size_t size;
35 
36  char *name;
37  time_t created;
38  int automatic;
39  u_int order;
40 
41  RB_ENTRY(paste_buffer) name_entry;
42  RB_ENTRY(paste_buffer) time_entry;
43 };
44 
45 static u_int paste_next_index;
46 static u_int paste_next_order;
47 static u_int paste_num_automatic;
48 static RB_HEAD(paste_name_tree, paste_buffer) paste_by_name;
49 static RB_HEAD(paste_time_tree, paste_buffer) paste_by_time;
50 
51 static int paste_cmp_names(const struct paste_buffer *,
52  const struct paste_buffer *);
53 RB_GENERATE_STATIC(paste_name_tree, paste_buffer, name_entry, paste_cmp_names);
54 
55 static int paste_cmp_times(const struct paste_buffer *,
56  const struct paste_buffer *);
57 RB_GENERATE_STATIC(paste_time_tree, paste_buffer, time_entry, paste_cmp_times);
58 
59 static int
60 paste_cmp_names(const struct paste_buffer *a, const struct paste_buffer *b)
61 {
62  return (strcmp(a->name, b->name));
63 }
64 
65 static int
66 paste_cmp_times(const struct paste_buffer *a, const struct paste_buffer *b)
67 {
68  if (a->order > b->order)
69  return (-1);
70  if (a->order < b->order)
71  return (1);
72  return (0);
73 }
74 
75 /* Get paste buffer name. */
76 const char *
78 {
79  return (pb->name);
80 }
81 
82 /* Get paste buffer order. */
83 u_int
85 {
86  return (pb->order);
87 }
88 
89 /* Get paste buffer created. */
90 time_t
92 {
93  return (pb->created);
94 }
95 
96 /* Get paste buffer data. */
97 const char *
98 paste_buffer_data(struct paste_buffer *pb, size_t *size)
99 {
100  if (size != NULL)
101  *size = pb->size;
102  return (pb->data);
103 }
104 
105 /* Walk paste buffers by time. */
106 struct paste_buffer *
108 {
109  if (pb == NULL)
110  return (RB_MIN(paste_time_tree, &paste_by_time));
111  return (RB_NEXT(paste_time_tree, &paste_by_time, pb));
112 }
113 
114 /* Get the most recent automatic buffer. */
115 struct paste_buffer *
116 paste_get_top(const char **name)
117 {
118  struct paste_buffer *pb;
119 
120  pb = RB_MIN(paste_time_tree, &paste_by_time);
121  if (pb == NULL)
122  return (NULL);
123  if (name != NULL)
124  *name = pb->name;
125  return (pb);
126 }
127 
128 /* Get a paste buffer by name. */
129 struct paste_buffer *
130 paste_get_name(const char *name)
131 {
132  struct paste_buffer pbfind;
133 
134  if (name == NULL || *name == '\0')
135  return (NULL);
136 
137  pbfind.name = (char *)name;
138  return (RB_FIND(paste_name_tree, &paste_by_name, &pbfind));
139 }
140 
141 /* Free a paste buffer. */
142 void
144 {
145  RB_REMOVE(paste_name_tree, &paste_by_name, pb);
146  RB_REMOVE(paste_time_tree, &paste_by_time, pb);
147  if (pb->automatic)
149 
150  free(pb->data);
151  free(pb->name);
152  free(pb);
153 }
154 
155 /*
156  * Add an automatic buffer, freeing the oldest automatic item if at limit. Note
157  * that the caller is responsible for allocating data.
158  */
159 void
160 paste_add(const char *prefix, char *data, size_t size)
161 {
162  struct paste_buffer *pb, *pb1;
163  u_int limit;
164 
165  if (prefix == NULL)
166  prefix = "buffer";
167 
168  if (size == 0) {
169  free(data);
170  return;
171  }
172 
173  limit = options_get_number(global_options, "buffer-limit");
174  RB_FOREACH_REVERSE_SAFE(pb, paste_time_tree, &paste_by_time, pb1) {
175  if (paste_num_automatic < limit)
176  break;
177  if (pb->automatic)
178  paste_free(pb);
179  }
180 
181  pb = xmalloc(sizeof *pb);
182 
183  pb->name = NULL;
184  do {
185  free(pb->name);
186  xasprintf(&pb->name, "%s%u", prefix, paste_next_index);
188  } while (paste_get_name(pb->name) != NULL);
189 
190  pb->data = data;
191  pb->size = size;
192 
193  pb->automatic = 1;
195 
196  pb->created = time(NULL);
197 
198  pb->order = paste_next_order++;
199  RB_INSERT(paste_name_tree, &paste_by_name, pb);
200  RB_INSERT(paste_time_tree, &paste_by_time, pb);
201 }
202 
203 /* Rename a paste buffer. */
204 int
205 paste_rename(const char *oldname, const char *newname, char **cause)
206 {
207  struct paste_buffer *pb, *pb_new;
208 
209  if (cause != NULL)
210  *cause = NULL;
211 
212  if (oldname == NULL || *oldname == '\0') {
213  if (cause != NULL)
214  *cause = xstrdup("no buffer");
215  return (-1);
216  }
217  if (newname == NULL || *newname == '\0') {
218  if (cause != NULL)
219  *cause = xstrdup("new name is empty");
220  return (-1);
221  }
222 
223  pb = paste_get_name(oldname);
224  if (pb == NULL) {
225  if (cause != NULL)
226  xasprintf(cause, "no buffer %s", oldname);
227  return (-1);
228  }
229 
230  pb_new = paste_get_name(newname);
231  if (pb_new != NULL) {
232  if (cause != NULL)
233  xasprintf(cause, "buffer %s already exists", newname);
234  return (-1);
235  }
236 
237  RB_REMOVE(paste_name_tree, &paste_by_name, pb);
238 
239  free(pb->name);
240  pb->name = xstrdup(newname);
241 
242  if (pb->automatic)
244  pb->automatic = 0;
245 
246  RB_INSERT(paste_name_tree, &paste_by_name, pb);
247 
248  return (0);
249 }
250 
251 /*
252  * Add or replace an item in the store. Note that the caller is responsible for
253  * allocating data.
254  */
255 int
256 paste_set(char *data, size_t size, const char *name, char **cause)
257 {
258  struct paste_buffer *pb, *old;
259 
260  if (cause != NULL)
261  *cause = NULL;
262 
263  if (size == 0) {
264  free(data);
265  return (0);
266  }
267  if (name == NULL) {
268  paste_add(NULL, data, size);
269  return (0);
270  }
271 
272  if (*name == '\0') {
273  if (cause != NULL)
274  *cause = xstrdup("empty buffer name");
275  return (-1);
276  }
277 
278  pb = xmalloc(sizeof *pb);
279 
280  pb->name = xstrdup(name);
281 
282  pb->data = data;
283  pb->size = size;
284 
285  pb->automatic = 0;
286  pb->order = paste_next_order++;
287 
288  pb->created = time(NULL);
289 
290  if ((old = paste_get_name(name)) != NULL)
291  paste_free(old);
292 
293  RB_INSERT(paste_name_tree, &paste_by_name, pb);
294  RB_INSERT(paste_time_tree, &paste_by_time, pb);
295 
296  return (0);
297 }
298 
299 /* Set paste data without otherwise changing it. */
300 void
301 paste_replace(struct paste_buffer *pb, char *data, size_t size)
302 {
303  free(pb->data);
304  pb->data = data;
305  pb->size = size;
306 }
307 
308 /* Convert start of buffer into a nice string. */
309 char *
311 {
312  char *buf;
313  size_t len, used;
314  const int flags = VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL;
315  const size_t width = 200;
316 
317  len = pb->size;
318  if (len > width)
319  len = width;
320  buf = xreallocarray(NULL, len, 4 + 4);
321 
322  used = utf8_strvis(buf, pb->data, len, flags);
323  if (pb->size > width || used > width)
324  strlcpy(buf + width, "...", 4);
325  return (buf);
326 }
RB_GENERATE_STATIC(args_tree, args_entry, entry, args_cmp)
size_t strlcpy(char *, const char *, size_t)
const char * name
Definition: layout-set.c:38
long long options_get_number(struct options *oo, const char *name)
Definition: options.c:699
const char * paste_buffer_name(struct paste_buffer *pb)
Definition: paste.c:77
int paste_set(char *data, size_t size, const char *name, char **cause)
Definition: paste.c:256
struct paste_buffer * paste_get_name(const char *name)
Definition: paste.c:130
time_t paste_buffer_created(struct paste_buffer *pb)
Definition: paste.c:91
static u_int paste_next_order
Definition: paste.c:46
void paste_add(const char *prefix, char *data, size_t size)
Definition: paste.c:160
struct paste_buffer * paste_get_top(const char **name)
Definition: paste.c:116
u_int paste_buffer_order(struct paste_buffer *pb)
Definition: paste.c:84
static RB_HEAD(RB_GENERATE_STATIC(paste_name_tree, RB_GENERATE_STATIC(paste_buffer)
Definition: paste.c:48
char * paste_make_sample(struct paste_buffer *pb)
Definition: paste.c:310
void paste_replace(struct paste_buffer *pb, char *data, size_t size)
Definition: paste.c:301
static u_int paste_num_automatic
Definition: paste.c:47
struct paste_buffer * paste_walk(struct paste_buffer *pb)
Definition: paste.c:107
static int paste_cmp_times(const struct paste_buffer *a, const struct paste_buffer *b)
Definition: paste.c:66
void paste_free(struct paste_buffer *pb)
Definition: paste.c:143
int paste_rename(const char *oldname, const char *newname, char **cause)
Definition: paste.c:205
static u_int paste_next_index
Definition: paste.c:45
const char * paste_buffer_data(struct paste_buffer *pb, size_t *size)
Definition: paste.c:98
size_t size
Definition: paste.c:34
char * name
Definition: paste.c:36
int automatic
Definition: paste.c:38
time_t created
Definition: paste.c:37
char * data
Definition: paste.c:33
u_int order
Definition: paste.c:39
struct options * global_options
Definition: tmux.c:36
int utf8_strvis(char *, const char *, size_t, int)
Definition: utf8.c:314
void * xmalloc(size_t size)
Definition: xmalloc.c:27
void * xreallocarray(void *ptr, size_t nmemb, size_t size)
Definition: xmalloc.c:61
int xasprintf(char **ret, const char *fmt,...)
Definition: xmalloc.c:109
char * xstrdup(const char *str)
Definition: xmalloc.c:89