/* $OpenBSD: paste.c,v 1.16 2014/03/31 21:39:31 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include "tmux.h" /* * Stack of paste buffers. Note that paste buffer data is not necessarily a C * string! */ /* Return each item of the stack in turn. */ struct paste_buffer * paste_walk_stack(struct paste_stack *ps, u_int *idx) { struct paste_buffer *pb; pb = paste_get_index(ps, *idx); (*idx)++; return (pb); } /* Get the top item on the stack. */ struct paste_buffer * paste_get_top(struct paste_stack *ps) { if (ARRAY_LENGTH(ps) == 0) return (NULL); return (ARRAY_FIRST(ps)); } /* Get an item by its index. */ struct paste_buffer * paste_get_index(struct paste_stack *ps, u_int idx) { if (idx >= ARRAY_LENGTH(ps)) return (NULL); return (ARRAY_ITEM(ps, idx)); } /* Free the top item on the stack. */ int paste_free_top(struct paste_stack *ps) { struct paste_buffer *pb; if (ARRAY_LENGTH(ps) == 0) return (-1); pb = ARRAY_FIRST(ps); ARRAY_REMOVE(ps, 0); free(pb->data); free(pb); return (0); } /* Free an item by index. */ int paste_free_index(struct paste_stack *ps, u_int idx) { struct paste_buffer *pb; if (idx >= ARRAY_LENGTH(ps)) return (-1); pb = ARRAY_ITEM(ps, idx); ARRAY_REMOVE(ps, idx); free(pb->data); free(pb); return (0); } /* * Add an item onto the top of the stack, freeing the bottom if at limit. Note * that the caller is responsible for allocating data. */ void paste_add(struct paste_stack *ps, char *data, size_t size, u_int limit) { struct paste_buffer *pb; if (size == 0) return; while (ARRAY_LENGTH(ps) >= limit) { pb = ARRAY_LAST(ps); free(pb->data); free(pb); ARRAY_TRUNC(ps, 1); } pb = xmalloc(sizeof *pb); ARRAY_INSERT(ps, 0, pb); pb->data = data; pb->size = size; } /* * Replace an item on the stack. Note that the caller is responsible for * allocating data. */ int paste_replace(struct paste_stack *ps, u_int idx, char *data, size_t size) { struct paste_buffer *pb; if (size == 0) { free(data); return (0); } if (idx >= ARRAY_LENGTH(ps)) return (-1); pb = ARRAY_ITEM(ps, idx); free(pb->data); pb->data = data; pb->size = size; return (0); } /* Convert a buffer into a visible string. */ char * paste_print(struct paste_buffer *pb, size_t width) { char *buf; size_t len, used; if (width < 3) width = 3; buf = xmalloc(width * 4 + 1); len = pb->size; if (len > width) len = width; used = strvisx(buf, pb->data, len, VIS_OCTAL|VIS_TAB|VIS_NL); if (pb->size > width || used > width) strlcpy(buf + width - 3, "...", 4); return (buf); } /* Paste into a window pane, filtering '\n' according to separator. */ void paste_send_pane(struct paste_buffer *pb, struct window_pane *wp, const char *sep, int bracket) { const char *data = pb->data, *end = data + pb->size, *lf; size_t seplen; if (bracket) bufferevent_write(wp->event, "\033[200~", 6); seplen = strlen(sep); while ((lf = memchr(data, '\n', end - data)) != NULL) { if (lf != data) bufferevent_write(wp->event, data, lf - data); bufferevent_write(wp->event, sep, seplen); data = lf + 1; } if (end != data) bufferevent_write(wp->event, data, end - data); if (bracket) bufferevent_write(wp->event, "\033[201~", 6); }