1 /* Id */ 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 <stdlib.h> 23 #include <string.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, u_int *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 free(pb->data); 74 free(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 free(pb->data); 92 free(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 free(pb->data); 112 free(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 free(data); 135 return (0); 136 } 137 138 if (idx >= ARRAY_LENGTH(ps)) 139 return (-1); 140 141 pb = ARRAY_ITEM(ps, idx); 142 free(pb->data); 143 144 pb->data = data; 145 pb->size = size; 146 147 return (0); 148 } 149 150 /* Convert a buffer into a visible string. */ 151 char * 152 paste_print(struct paste_buffer *pb, size_t width) 153 { 154 char *buf; 155 size_t len, used; 156 157 if (width < 3) 158 width = 3; 159 buf = xmalloc(width * 4 + 1); 160 161 len = pb->size; 162 if (len > width) 163 len = width; 164 165 used = strvisx(buf, pb->data, len, VIS_OCTAL|VIS_TAB|VIS_NL); 166 if (pb->size > width || used > width) 167 strlcpy(buf + width - 3, "...", 4); 168 169 return (buf); 170 } 171 172 /* Paste into a window pane, filtering '\n' according to separator. */ 173 void 174 paste_send_pane (struct paste_buffer *pb, struct window_pane *wp, 175 const char *sep, int bracket) 176 { 177 const char *data = pb->data, *end = data + pb->size, *lf; 178 size_t seplen; 179 180 if (bracket) 181 bufferevent_write(wp->event, "\033[200~", 6); 182 183 seplen = strlen(sep); 184 while ((lf = memchr(data, '\n', end - data)) != NULL) { 185 if (lf != data) 186 bufferevent_write(wp->event, data, lf - data); 187 bufferevent_write(wp->event, sep, seplen); 188 data = lf + 1; 189 } 190 191 if (end != data) 192 bufferevent_write(wp->event, data, end - data); 193 194 if (bracket) 195 bufferevent_write(wp->event, "\033[201~", 6); 196 } 197