Home | History | Annotate | Line # | Download | only in dist
cmd-capture-pane.c revision 1.6.4.1
      1      1.3  christos /* $OpenBSD$ */
      2      1.1      jmmv 
      3      1.1      jmmv /*
      4      1.1      jmmv  * Copyright (c) 2009 Jonathan Alvarado <radobobo (at) users.sourceforge.net>
      5      1.1      jmmv  *
      6      1.1      jmmv  * Permission to use, copy, modify, and distribute this software for any
      7      1.1      jmmv  * purpose with or without fee is hereby granted, provided that the above
      8      1.1      jmmv  * copyright notice and this permission notice appear in all copies.
      9      1.1      jmmv  *
     10      1.1      jmmv  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     11      1.1      jmmv  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     12      1.1      jmmv  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     13      1.1      jmmv  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     14      1.1      jmmv  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
     15      1.1      jmmv  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
     16      1.1      jmmv  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     17      1.1      jmmv  */
     18      1.1      jmmv 
     19      1.1      jmmv #include <sys/types.h>
     20      1.1      jmmv 
     21      1.2  christos #include <stdlib.h>
     22      1.1      jmmv #include <string.h>
     23      1.1      jmmv 
     24      1.1      jmmv #include "tmux.h"
     25      1.1      jmmv 
     26      1.1      jmmv /*
     27      1.2  christos  * Write the entire contents of a pane to a buffer or stdout.
     28      1.1      jmmv  */
     29      1.1      jmmv 
     30      1.5  christos static enum cmd_retval	cmd_capture_pane_exec(struct cmd *, struct cmdq_item *);
     31      1.2  christos 
     32      1.5  christos static char	*cmd_capture_pane_append(char *, size_t *, char *, size_t);
     33      1.5  christos static char	*cmd_capture_pane_pending(struct args *, struct window_pane *,
     34      1.2  christos 		     size_t *);
     35      1.5  christos static char	*cmd_capture_pane_history(struct args *, struct cmdq_item *,
     36      1.2  christos 		     struct window_pane *, size_t *);
     37      1.1      jmmv 
     38      1.1      jmmv const struct cmd_entry cmd_capture_pane_entry = {
     39      1.4  christos 	.name = "capture-pane",
     40      1.4  christos 	.alias = "capturep",
     41      1.4  christos 
     42      1.4  christos 	.args = { "ab:CeE:JpPqS:t:", 0, 0 },
     43      1.4  christos 	.usage = "[-aCeJpPq] " CMD_BUFFER_USAGE " [-E end-line] "
     44  1.6.4.1    martin 		 "[-S start-line] " CMD_TARGET_PANE_USAGE,
     45      1.4  christos 
     46      1.6  christos 	.target = { 't', CMD_FIND_PANE, 0 },
     47      1.4  christos 
     48      1.5  christos 	.flags = CMD_AFTERHOOK,
     49      1.4  christos 	.exec = cmd_capture_pane_exec
     50      1.1      jmmv };
     51      1.1      jmmv 
     52      1.5  christos const struct cmd_entry cmd_clear_history_entry = {
     53      1.5  christos 	.name = "clear-history",
     54      1.5  christos 	.alias = "clearhist",
     55      1.5  christos 
     56      1.5  christos 	.args = { "t:", 0, 0 },
     57      1.5  christos 	.usage = CMD_TARGET_PANE_USAGE,
     58      1.5  christos 
     59      1.6  christos 	.target = { 't', CMD_FIND_PANE, 0 },
     60      1.5  christos 
     61      1.5  christos 	.flags = CMD_AFTERHOOK,
     62      1.5  christos 	.exec = cmd_capture_pane_exec
     63      1.5  christos };
     64      1.5  christos 
     65      1.5  christos static char *
     66      1.2  christos cmd_capture_pane_append(char *buf, size_t *len, char *line, size_t linelen)
     67      1.2  christos {
     68      1.3  christos 	buf = xrealloc(buf, *len + linelen + 1);
     69      1.2  christos 	memcpy(buf + *len, line, linelen);
     70      1.2  christos 	*len += linelen;
     71      1.2  christos 	return (buf);
     72      1.2  christos }
     73      1.2  christos 
     74      1.5  christos static char *
     75      1.2  christos cmd_capture_pane_pending(struct args *args, struct window_pane *wp,
     76      1.2  christos     size_t *len)
     77      1.2  christos {
     78      1.3  christos 	struct evbuffer	*pending;
     79      1.3  christos 	char		*buf, *line, tmp[5];
     80      1.3  christos 	size_t		 linelen;
     81      1.3  christos 	u_int		 i;
     82      1.2  christos 
     83      1.3  christos 	pending = input_pending(wp);
     84      1.3  christos 	if (pending == NULL)
     85      1.2  christos 		return (xstrdup(""));
     86      1.2  christos 
     87      1.3  christos 	line = (char *)EVBUFFER_DATA(pending);
     88      1.3  christos 	linelen = EVBUFFER_LENGTH(pending);
     89      1.2  christos 
     90      1.2  christos 	buf = xstrdup("");
     91      1.2  christos 	if (args_has(args, 'C')) {
     92      1.2  christos 		for (i = 0; i < linelen; i++) {
     93      1.5  christos 			if (line[i] >= ' ' && line[i] != '\\') {
     94      1.2  christos 				tmp[0] = line[i];
     95      1.2  christos 				tmp[1] = '\0';
     96      1.2  christos 			} else
     97      1.3  christos 				xsnprintf(tmp, sizeof tmp, "\\%03hho", line[i]);
     98      1.2  christos 			buf = cmd_capture_pane_append(buf, len, tmp,
     99      1.2  christos 			    strlen(tmp));
    100      1.2  christos 		}
    101      1.2  christos 	} else
    102      1.2  christos 		buf = cmd_capture_pane_append(buf, len, line, linelen);
    103      1.2  christos 	return (buf);
    104      1.2  christos }
    105      1.2  christos 
    106      1.5  christos static char *
    107      1.5  christos cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
    108      1.2  christos     struct window_pane *wp, size_t *len)
    109      1.1      jmmv {
    110      1.2  christos 	struct grid		*gd;
    111      1.2  christos 	const struct grid_line	*gl;
    112      1.2  christos 	struct grid_cell	*gc = NULL;
    113      1.2  christos 	int			 n, with_codes, escape_c0, join_lines;
    114      1.2  christos 	u_int			 i, sx, top, bottom, tmp;
    115      1.2  christos 	char			*cause, *buf, *line;
    116      1.3  christos 	const char		*Sflag, *Eflag;
    117      1.2  christos 	size_t			 linelen;
    118      1.2  christos 
    119      1.2  christos 	sx = screen_size_x(&wp->base);
    120      1.2  christos 	if (args_has(args, 'a')) {
    121      1.2  christos 		gd = wp->saved_grid;
    122      1.2  christos 		if (gd == NULL) {
    123      1.2  christos 			if (!args_has(args, 'q')) {
    124      1.5  christos 				cmdq_error(item, "no alternate screen");
    125      1.2  christos 				return (NULL);
    126      1.2  christos 			}
    127      1.2  christos 			return (xstrdup(""));
    128      1.2  christos 		}
    129      1.2  christos 	} else
    130      1.2  christos 		gd = wp->base.grid;
    131      1.2  christos 
    132      1.3  christos 	Sflag = args_get(args, 'S');
    133      1.3  christos 	if (Sflag != NULL && strcmp(Sflag, "-") == 0)
    134      1.2  christos 		top = 0;
    135      1.3  christos 	else {
    136      1.3  christos 		n = args_strtonum(args, 'S', INT_MIN, SHRT_MAX, &cause);
    137      1.3  christos 		if (cause != NULL) {
    138      1.3  christos 			top = gd->hsize;
    139      1.3  christos 			free(cause);
    140      1.3  christos 		} else if (n < 0 && (u_int) -n > gd->hsize)
    141      1.3  christos 			top = 0;
    142      1.3  christos 		else
    143      1.3  christos 			top = gd->hsize + n;
    144      1.3  christos 		if (top > gd->hsize + gd->sy - 1)
    145      1.3  christos 			top = gd->hsize + gd->sy - 1;
    146      1.3  christos 	}
    147      1.2  christos 
    148      1.3  christos 	Eflag = args_get(args, 'E');
    149      1.3  christos 	if (Eflag != NULL && strcmp(Eflag, "-") == 0)
    150      1.2  christos 		bottom = gd->hsize + gd->sy - 1;
    151      1.3  christos 	else {
    152      1.3  christos 		n = args_strtonum(args, 'E', INT_MIN, SHRT_MAX, &cause);
    153      1.3  christos 		if (cause != NULL) {
    154      1.3  christos 			bottom = gd->hsize + gd->sy - 1;
    155      1.3  christos 			free(cause);
    156      1.3  christos 		} else if (n < 0 && (u_int) -n > gd->hsize)
    157      1.3  christos 			bottom = 0;
    158      1.3  christos 		else
    159      1.3  christos 			bottom = gd->hsize + n;
    160      1.3  christos 		if (bottom > gd->hsize + gd->sy - 1)
    161      1.3  christos 			bottom = gd->hsize + gd->sy - 1;
    162      1.3  christos 	}
    163      1.2  christos 
    164      1.2  christos 	if (bottom < top) {
    165      1.2  christos 		tmp = bottom;
    166      1.2  christos 		bottom = top;
    167      1.2  christos 		top = tmp;
    168      1.2  christos 	}
    169      1.2  christos 
    170      1.2  christos 	with_codes = args_has(args, 'e');
    171      1.2  christos 	escape_c0 = args_has(args, 'C');
    172      1.2  christos 	join_lines = args_has(args, 'J');
    173      1.1      jmmv 
    174      1.1      jmmv 	buf = NULL;
    175      1.2  christos 	for (i = top; i <= bottom; i++) {
    176      1.2  christos 		line = grid_string_cells(gd, 0, i, sx, &gc, with_codes,
    177      1.2  christos 		    escape_c0, !join_lines);
    178      1.2  christos 		linelen = strlen(line);
    179      1.2  christos 
    180      1.2  christos 		buf = cmd_capture_pane_append(buf, len, line, linelen);
    181      1.2  christos 
    182      1.2  christos 		gl = grid_peek_line(gd, i);
    183      1.2  christos 		if (!join_lines || !(gl->flags & GRID_LINE_WRAPPED))
    184      1.2  christos 			buf[(*len)++] = '\n';
    185      1.2  christos 
    186      1.2  christos 		free(line);
    187      1.2  christos 	}
    188      1.2  christos 	return (buf);
    189      1.2  christos }
    190      1.2  christos 
    191      1.5  christos static enum cmd_retval
    192      1.5  christos cmd_capture_pane_exec(struct cmd *self, struct cmdq_item *item)
    193      1.2  christos {
    194      1.2  christos 	struct args		*args = self->args;
    195      1.2  christos 	struct client		*c;
    196      1.6  christos 	struct window_pane	*wp = item->target.wp;
    197      1.2  christos 	char			*buf, *cause;
    198      1.3  christos 	const char		*bufname;
    199      1.2  christos 	size_t			 len;
    200      1.1      jmmv 
    201      1.5  christos 	if (self->entry == &cmd_clear_history_entry) {
    202  1.6.4.1    martin 		window_pane_reset_mode_all(wp);
    203      1.5  christos 		grid_clear_history(wp->base.grid);
    204      1.5  christos 		return (CMD_RETURN_NORMAL);
    205      1.5  christos 	}
    206      1.5  christos 
    207      1.2  christos 	len = 0;
    208      1.2  christos 	if (args_has(args, 'P'))
    209      1.2  christos 		buf = cmd_capture_pane_pending(args, wp, &len);
    210      1.2  christos 	else
    211      1.5  christos 		buf = cmd_capture_pane_history(args, item, wp, &len);
    212      1.2  christos 	if (buf == NULL)
    213      1.2  christos 		return (CMD_RETURN_ERROR);
    214      1.2  christos 
    215      1.2  christos 	if (args_has(args, 'p')) {
    216      1.5  christos 		c = item->client;
    217      1.2  christos 		if (c == NULL ||
    218      1.2  christos 		    (c->session != NULL && !(c->flags & CLIENT_CONTROL))) {
    219      1.5  christos 			cmdq_error(item, "can't write to stdout");
    220      1.3  christos 			free(buf);
    221      1.2  christos 			return (CMD_RETURN_ERROR);
    222      1.2  christos 		}
    223      1.2  christos 		evbuffer_add(c->stdout_data, buf, len);
    224      1.3  christos 		free(buf);
    225      1.2  christos 		if (args_has(args, 'P') && len > 0)
    226      1.2  christos 		    evbuffer_add(c->stdout_data, "\n", 1);
    227      1.4  christos 		server_client_push_stdout(c);
    228      1.2  christos 	} else {
    229      1.3  christos 		bufname = NULL;
    230      1.3  christos 		if (args_has(args, 'b'))
    231      1.3  christos 			bufname = args_get(args, 'b');
    232      1.2  christos 
    233      1.3  christos 		if (paste_set(buf, len, bufname, &cause) != 0) {
    234      1.5  christos 			cmdq_error(item, "%s", cause);
    235      1.2  christos 			free(cause);
    236      1.2  christos 			free(buf);
    237      1.2  christos 			return (CMD_RETURN_ERROR);
    238      1.2  christos 		}
    239      1.1      jmmv 	}
    240      1.1      jmmv 
    241      1.2  christos 	return (CMD_RETURN_NORMAL);
    242      1.1      jmmv }
    243