File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / tmux / cmd-capture-pane.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 14 12:22:44 2017 UTC (6 years, 11 months ago) by misho
Branches: tmux, MAIN
CVS tags: v2_4p0, v2_4, HEAD
tmux 2.4

    1: /* $OpenBSD$ */
    2: 
    3: /*
    4:  * Copyright (c) 2009 Jonathan Alvarado <radobobo@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: 
   21: #include <stdlib.h>
   22: #include <string.h>
   23: 
   24: #include "tmux.h"
   25: 
   26: /*
   27:  * Write the entire contents of a pane to a buffer or stdout.
   28:  */
   29: 
   30: static enum cmd_retval	cmd_capture_pane_exec(struct cmd *, struct cmdq_item *);
   31: 
   32: static char	*cmd_capture_pane_append(char *, size_t *, char *, size_t);
   33: static char	*cmd_capture_pane_pending(struct args *, struct window_pane *,
   34: 		     size_t *);
   35: static char	*cmd_capture_pane_history(struct args *, struct cmdq_item *,
   36: 		     struct window_pane *, size_t *);
   37: 
   38: const struct cmd_entry cmd_capture_pane_entry = {
   39: 	.name = "capture-pane",
   40: 	.alias = "capturep",
   41: 
   42: 	.args = { "ab:CeE:JpPqS:t:", 0, 0 },
   43: 	.usage = "[-aCeJpPq] " CMD_BUFFER_USAGE " [-E end-line] "
   44: 		 "[-S start-line]" CMD_TARGET_PANE_USAGE,
   45: 
   46: 	.tflag = CMD_PANE,
   47: 
   48: 	.flags = CMD_AFTERHOOK,
   49: 	.exec = cmd_capture_pane_exec
   50: };
   51: 
   52: const struct cmd_entry cmd_clear_history_entry = {
   53: 	.name = "clear-history",
   54: 	.alias = "clearhist",
   55: 
   56: 	.args = { "t:", 0, 0 },
   57: 	.usage = CMD_TARGET_PANE_USAGE,
   58: 
   59: 	.tflag = CMD_PANE,
   60: 
   61: 	.flags = CMD_AFTERHOOK,
   62: 	.exec = cmd_capture_pane_exec
   63: };
   64: 
   65: static char *
   66: cmd_capture_pane_append(char *buf, size_t *len, char *line, size_t linelen)
   67: {
   68: 	buf = xrealloc(buf, *len + linelen + 1);
   69: 	memcpy(buf + *len, line, linelen);
   70: 	*len += linelen;
   71: 	return (buf);
   72: }
   73: 
   74: static char *
   75: cmd_capture_pane_pending(struct args *args, struct window_pane *wp,
   76:     size_t *len)
   77: {
   78: 	struct evbuffer	*pending;
   79: 	char		*buf, *line, tmp[5];
   80: 	size_t		 linelen;
   81: 	u_int		 i;
   82: 
   83: 	pending = input_pending(wp);
   84: 	if (pending == NULL)
   85: 		return (xstrdup(""));
   86: 
   87: 	line = EVBUFFER_DATA(pending);
   88: 	linelen = EVBUFFER_LENGTH(pending);
   89: 
   90: 	buf = xstrdup("");
   91: 	if (args_has(args, 'C')) {
   92: 		for (i = 0; i < linelen; i++) {
   93: 			if (line[i] >= ' ' && line[i] != '\\') {
   94: 				tmp[0] = line[i];
   95: 				tmp[1] = '\0';
   96: 			} else
   97: 				xsnprintf(tmp, sizeof tmp, "\\%03hho", line[i]);
   98: 			buf = cmd_capture_pane_append(buf, len, tmp,
   99: 			    strlen(tmp));
  100: 		}
  101: 	} else
  102: 		buf = cmd_capture_pane_append(buf, len, line, linelen);
  103: 	return (buf);
  104: }
  105: 
  106: static char *
  107: cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
  108:     struct window_pane *wp, size_t *len)
  109: {
  110: 	struct grid		*gd;
  111: 	const struct grid_line	*gl;
  112: 	struct grid_cell	*gc = NULL;
  113: 	int			 n, with_codes, escape_c0, join_lines;
  114: 	u_int			 i, sx, top, bottom, tmp;
  115: 	char			*cause, *buf, *line;
  116: 	const char		*Sflag, *Eflag;
  117: 	size_t			 linelen;
  118: 
  119: 	sx = screen_size_x(&wp->base);
  120: 	if (args_has(args, 'a')) {
  121: 		gd = wp->saved_grid;
  122: 		if (gd == NULL) {
  123: 			if (!args_has(args, 'q')) {
  124: 				cmdq_error(item, "no alternate screen");
  125: 				return (NULL);
  126: 			}
  127: 			return (xstrdup(""));
  128: 		}
  129: 	} else
  130: 		gd = wp->base.grid;
  131: 
  132: 	Sflag = args_get(args, 'S');
  133: 	if (Sflag != NULL && strcmp(Sflag, "-") == 0)
  134: 		top = 0;
  135: 	else {
  136: 		n = args_strtonum(args, 'S', INT_MIN, SHRT_MAX, &cause);
  137: 		if (cause != NULL) {
  138: 			top = gd->hsize;
  139: 			free(cause);
  140: 		} else if (n < 0 && (u_int) -n > gd->hsize)
  141: 			top = 0;
  142: 		else
  143: 			top = gd->hsize + n;
  144: 		if (top > gd->hsize + gd->sy - 1)
  145: 			top = gd->hsize + gd->sy - 1;
  146: 	}
  147: 
  148: 	Eflag = args_get(args, 'E');
  149: 	if (Eflag != NULL && strcmp(Eflag, "-") == 0)
  150: 		bottom = gd->hsize + gd->sy - 1;
  151: 	else {
  152: 		n = args_strtonum(args, 'E', INT_MIN, SHRT_MAX, &cause);
  153: 		if (cause != NULL) {
  154: 			bottom = gd->hsize + gd->sy - 1;
  155: 			free(cause);
  156: 		} else if (n < 0 && (u_int) -n > gd->hsize)
  157: 			bottom = 0;
  158: 		else
  159: 			bottom = gd->hsize + n;
  160: 		if (bottom > gd->hsize + gd->sy - 1)
  161: 			bottom = gd->hsize + gd->sy - 1;
  162: 	}
  163: 
  164: 	if (bottom < top) {
  165: 		tmp = bottom;
  166: 		bottom = top;
  167: 		top = tmp;
  168: 	}
  169: 
  170: 	with_codes = args_has(args, 'e');
  171: 	escape_c0 = args_has(args, 'C');
  172: 	join_lines = args_has(args, 'J');
  173: 
  174: 	buf = NULL;
  175: 	for (i = top; i <= bottom; i++) {
  176: 		line = grid_string_cells(gd, 0, i, sx, &gc, with_codes,
  177: 		    escape_c0, !join_lines);
  178: 		linelen = strlen(line);
  179: 
  180: 		buf = cmd_capture_pane_append(buf, len, line, linelen);
  181: 
  182: 		gl = grid_peek_line(gd, i);
  183: 		if (!join_lines || !(gl->flags & GRID_LINE_WRAPPED))
  184: 			buf[(*len)++] = '\n';
  185: 
  186: 		free(line);
  187: 	}
  188: 	return (buf);
  189: }
  190: 
  191: static enum cmd_retval
  192: cmd_capture_pane_exec(struct cmd *self, struct cmdq_item *item)
  193: {
  194: 	struct args		*args = self->args;
  195: 	struct client		*c;
  196: 	struct window_pane	*wp = item->state.tflag.wp;
  197: 	char			*buf, *cause;
  198: 	const char		*bufname;
  199: 	size_t			 len;
  200: 
  201: 	if (self->entry == &cmd_clear_history_entry) {
  202: 		if (wp->mode == &window_copy_mode)
  203: 			window_pane_reset_mode(wp);
  204: 		grid_clear_history(wp->base.grid);
  205: 		return (CMD_RETURN_NORMAL);
  206: 	}
  207: 
  208: 	len = 0;
  209: 	if (args_has(args, 'P'))
  210: 		buf = cmd_capture_pane_pending(args, wp, &len);
  211: 	else
  212: 		buf = cmd_capture_pane_history(args, item, wp, &len);
  213: 	if (buf == NULL)
  214: 		return (CMD_RETURN_ERROR);
  215: 
  216: 	if (args_has(args, 'p')) {
  217: 		c = item->client;
  218: 		if (c == NULL ||
  219: 		    (c->session != NULL && !(c->flags & CLIENT_CONTROL))) {
  220: 			cmdq_error(item, "can't write to stdout");
  221: 			free(buf);
  222: 			return (CMD_RETURN_ERROR);
  223: 		}
  224: 		evbuffer_add(c->stdout_data, buf, len);
  225: 		free(buf);
  226: 		if (args_has(args, 'P') && len > 0)
  227: 		    evbuffer_add(c->stdout_data, "\n", 1);
  228: 		server_client_push_stdout(c);
  229: 	} else {
  230: 		bufname = NULL;
  231: 		if (args_has(args, 'b'))
  232: 			bufname = args_get(args, 'b');
  233: 
  234: 		if (paste_set(buf, len, bufname, &cause) != 0) {
  235: 			cmdq_error(item, "%s", cause);
  236: 			free(cause);
  237: 			free(buf);
  238: 			return (CMD_RETURN_ERROR);
  239: 		}
  240: 	}
  241: 
  242: 	return (CMD_RETURN_NORMAL);
  243: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>