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