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