Home | History | Annotate | Line # | Download | only in dist
cmd-capture-pane.c revision 1.7
      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.7  christos 		 "[-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.7  christos 		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