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