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