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. */ 32struct paste_buffer * 33paste_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. */ 43struct paste_buffer * 44paste_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. */ 52struct paste_buffer * 53paste_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. */ 61int 62paste_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. */ 79int 80paste_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 */ 100void 101paste_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 */ 127int 128paste_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. */ 148char * 149paste_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