Home | History | Annotate | Line # | Download | only in dist
cmd-capture-pane.c revision 1.1.1.11
      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.7  christos static enum cmd_retval	cmd_capture_pane_exec(struct cmd *, struct cmdq_item *);
     31   1.1.1.3  christos 
     32   1.1.1.7  christos static char	*cmd_capture_pane_append(char *, size_t *, char *, size_t);
     33   1.1.1.7  christos static char	*cmd_capture_pane_pending(struct args *, struct window_pane *,
     34   1.1.1.3  christos 		     size_t *);
     35   1.1.1.7  christos static char	*cmd_capture_pane_history(struct args *, struct cmdq_item *,
     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.1.6  christos 	.name = "capture-pane",
     40   1.1.1.6  christos 	.alias = "capturep",
     41   1.1.1.6  christos 
     42  1.1.1.10  christos 	.args = { "ab:CeE:JNpPqS:t:", 0, 0 },
     43  1.1.1.10  christos 	.usage = "[-aCeJNpPq] " CMD_BUFFER_USAGE " [-E end-line] "
     44   1.1.1.9  christos 		 "[-S start-line] " CMD_TARGET_PANE_USAGE,
     45   1.1.1.6  christos 
     46   1.1.1.8  christos 	.target = { 't', CMD_FIND_PANE, 0 },
     47   1.1.1.6  christos 
     48   1.1.1.7  christos 	.flags = CMD_AFTERHOOK,
     49   1.1.1.6  christos 	.exec = cmd_capture_pane_exec
     50       1.1      jmmv };
     51       1.1      jmmv 
     52   1.1.1.7  christos const struct cmd_entry cmd_clear_history_entry = {
     53   1.1.1.7  christos 	.name = "clear-history",
     54   1.1.1.7  christos 	.alias = "clearhist",
     55   1.1.1.7  christos 
     56   1.1.1.7  christos 	.args = { "t:", 0, 0 },
     57   1.1.1.7  christos 	.usage = CMD_TARGET_PANE_USAGE,
     58   1.1.1.7  christos 
     59   1.1.1.8  christos 	.target = { 't', CMD_FIND_PANE, 0 },
     60   1.1.1.7  christos 
     61   1.1.1.7  christos 	.flags = CMD_AFTERHOOK,
     62   1.1.1.7  christos 	.exec = cmd_capture_pane_exec
     63   1.1.1.7  christos };
     64   1.1.1.7  christos 
     65   1.1.1.7  christos static char *
     66   1.1.1.3  christos cmd_capture_pane_append(char *buf, size_t *len, char *line, size_t linelen)
     67       1.1      jmmv {
     68   1.1.1.5  christos 	buf = xrealloc(buf, *len + linelen + 1);
     69   1.1.1.3  christos 	memcpy(buf + *len, line, linelen);
     70   1.1.1.3  christos 	*len += linelen;
     71   1.1.1.3  christos 	return (buf);
     72   1.1.1.3  christos }
     73       1.1      jmmv 
     74   1.1.1.7  christos static char *
     75   1.1.1.3  christos cmd_capture_pane_pending(struct args *args, struct window_pane *wp,
     76   1.1.1.3  christos     size_t *len)
     77   1.1.1.3  christos {
     78   1.1.1.5  christos 	struct evbuffer	*pending;
     79   1.1.1.5  christos 	char		*buf, *line, tmp[5];
     80   1.1.1.5  christos 	size_t		 linelen;
     81   1.1.1.5  christos 	u_int		 i;
     82   1.1.1.3  christos 
     83  1.1.1.11  christos 	pending = input_pending(wp->ictx);
     84   1.1.1.5  christos 	if (pending == NULL)
     85   1.1.1.3  christos 		return (xstrdup(""));
     86   1.1.1.3  christos 
     87   1.1.1.5  christos 	line = EVBUFFER_DATA(pending);
     88   1.1.1.5  christos 	linelen = EVBUFFER_LENGTH(pending);
     89   1.1.1.3  christos 
     90   1.1.1.3  christos 	buf = xstrdup("");
     91   1.1.1.3  christos 	if (args_has(args, 'C')) {
     92   1.1.1.3  christos 		for (i = 0; i < linelen; i++) {
     93   1.1.1.7  christos 			if (line[i] >= ' ' && line[i] != '\\') {
     94   1.1.1.3  christos 				tmp[0] = line[i];
     95   1.1.1.3  christos 				tmp[1] = '\0';
     96   1.1.1.3  christos 			} else
     97   1.1.1.5  christos 				xsnprintf(tmp, sizeof tmp, "\\%03hho", line[i]);
     98   1.1.1.3  christos 			buf = cmd_capture_pane_append(buf, len, tmp,
     99   1.1.1.3  christos 			    strlen(tmp));
    100   1.1.1.3  christos 		}
    101   1.1.1.3  christos 	} else
    102   1.1.1.3  christos 		buf = cmd_capture_pane_append(buf, len, line, linelen);
    103   1.1.1.3  christos 	return (buf);
    104   1.1.1.3  christos }
    105   1.1.1.3  christos 
    106   1.1.1.7  christos static char *
    107   1.1.1.7  christos cmd_capture_pane_history(struct args *args, struct cmdq_item *item,
    108   1.1.1.3  christos     struct window_pane *wp, size_t *len)
    109   1.1.1.3  christos {
    110   1.1.1.3  christos 	struct grid		*gd;
    111   1.1.1.3  christos 	const struct grid_line	*gl;
    112   1.1.1.3  christos 	struct grid_cell	*gc = NULL;
    113  1.1.1.10  christos 	int			 n, with_codes, escape_c0, join_lines, no_trim;
    114   1.1.1.3  christos 	u_int			 i, sx, top, bottom, tmp;
    115   1.1.1.3  christos 	char			*cause, *buf, *line;
    116   1.1.1.5  christos 	const char		*Sflag, *Eflag;
    117   1.1.1.3  christos 	size_t			 linelen;
    118   1.1.1.3  christos 
    119   1.1.1.3  christos 	sx = screen_size_x(&wp->base);
    120   1.1.1.3  christos 	if (args_has(args, 'a')) {
    121  1.1.1.11  christos 		gd = wp->base.saved_grid;
    122   1.1.1.3  christos 		if (gd == NULL) {
    123   1.1.1.3  christos 			if (!args_has(args, 'q')) {
    124   1.1.1.7  christos 				cmdq_error(item, "no alternate screen");
    125   1.1.1.3  christos 				return (NULL);
    126   1.1.1.3  christos 			}
    127   1.1.1.3  christos 			return (xstrdup(""));
    128   1.1.1.3  christos 		}
    129   1.1.1.3  christos 	} else
    130   1.1.1.3  christos 		gd = wp->base.grid;
    131       1.1      jmmv 
    132   1.1.1.5  christos 	Sflag = args_get(args, 'S');
    133   1.1.1.5  christos 	if (Sflag != NULL && strcmp(Sflag, "-") == 0)
    134   1.1.1.2      jmmv 		top = 0;
    135   1.1.1.5  christos 	else {
    136   1.1.1.5  christos 		n = args_strtonum(args, 'S', INT_MIN, SHRT_MAX, &cause);
    137   1.1.1.5  christos 		if (cause != NULL) {
    138   1.1.1.5  christos 			top = gd->hsize;
    139   1.1.1.5  christos 			free(cause);
    140   1.1.1.5  christos 		} else if (n < 0 && (u_int) -n > gd->hsize)
    141   1.1.1.5  christos 			top = 0;
    142   1.1.1.5  christos 		else
    143   1.1.1.5  christos 			top = gd->hsize + n;
    144   1.1.1.5  christos 		if (top > gd->hsize + gd->sy - 1)
    145   1.1.1.5  christos 			top = gd->hsize + gd->sy - 1;
    146   1.1.1.5  christos 	}
    147   1.1.1.2      jmmv 
    148   1.1.1.5  christos 	Eflag = args_get(args, 'E');
    149   1.1.1.5  christos 	if (Eflag != NULL && strcmp(Eflag, "-") == 0)
    150   1.1.1.2      jmmv 		bottom = gd->hsize + gd->sy - 1;
    151   1.1.1.5  christos 	else {
    152   1.1.1.5  christos 		n = args_strtonum(args, 'E', INT_MIN, SHRT_MAX, &cause);
    153   1.1.1.5  christos 		if (cause != NULL) {
    154   1.1.1.5  christos 			bottom = gd->hsize + gd->sy - 1;
    155   1.1.1.5  christos 			free(cause);
    156   1.1.1.5  christos 		} else if (n < 0 && (u_int) -n > gd->hsize)
    157   1.1.1.5  christos 			bottom = 0;
    158   1.1.1.5  christos 		else
    159   1.1.1.5  christos 			bottom = gd->hsize + n;
    160   1.1.1.5  christos 		if (bottom > gd->hsize + gd->sy - 1)
    161   1.1.1.5  christos 			bottom = gd->hsize + gd->sy - 1;
    162   1.1.1.5  christos 	}
    163   1.1.1.2      jmmv 
    164   1.1.1.2      jmmv 	if (bottom < top) {
    165   1.1.1.2      jmmv 		tmp = bottom;
    166   1.1.1.2      jmmv 		bottom = top;
    167   1.1.1.2      jmmv 		top = tmp;
    168   1.1.1.2      jmmv 	}
    169   1.1.1.2      jmmv 
    170   1.1.1.3  christos 	with_codes = args_has(args, 'e');
    171   1.1.1.3  christos 	escape_c0 = args_has(args, 'C');
    172   1.1.1.3  christos 	join_lines = args_has(args, 'J');
    173  1.1.1.10  christos 	no_trim = args_has(args, 'N');
    174       1.1      jmmv 
    175   1.1.1.3  christos 	buf = NULL;
    176   1.1.1.3  christos 	for (i = top; i <= bottom; i++) {
    177   1.1.1.3  christos 		line = grid_string_cells(gd, 0, i, sx, &gc, with_codes,
    178  1.1.1.10  christos 		    escape_c0, !join_lines && !no_trim);
    179   1.1.1.3  christos 		linelen = strlen(line);
    180       1.1      jmmv 
    181   1.1.1.3  christos 		buf = cmd_capture_pane_append(buf, len, line, linelen);
    182       1.1      jmmv 
    183   1.1.1.3  christos 		gl = grid_peek_line(gd, i);
    184   1.1.1.3  christos 		if (!join_lines || !(gl->flags & GRID_LINE_WRAPPED))
    185   1.1.1.3  christos 			buf[(*len)++] = '\n';
    186   1.1.1.2      jmmv 
    187   1.1.1.3  christos 		free(line);
    188       1.1      jmmv 	}
    189   1.1.1.3  christos 	return (buf);
    190   1.1.1.3  christos }
    191   1.1.1.2      jmmv 
    192   1.1.1.7  christos static enum cmd_retval
    193   1.1.1.7  christos cmd_capture_pane_exec(struct cmd *self, struct cmdq_item *item)
    194   1.1.1.3  christos {
    195  1.1.1.11  christos 	struct args		*args = cmd_get_args(self);
    196  1.1.1.11  christos 	struct client		*c = cmdq_get_client(item);
    197  1.1.1.11  christos 	struct window_pane	*wp = cmdq_get_target(item)->wp;
    198   1.1.1.3  christos 	char			*buf, *cause;
    199   1.1.1.5  christos 	const char		*bufname;
    200   1.1.1.3  christos 	size_t			 len;
    201   1.1.1.2      jmmv 
    202  1.1.1.11  christos 	if (cmd_get_entry(self) == &cmd_clear_history_entry) {
    203   1.1.1.9  christos 		window_pane_reset_mode_all(wp);
    204   1.1.1.7  christos 		grid_clear_history(wp->base.grid);
    205   1.1.1.7  christos 		return (CMD_RETURN_NORMAL);
    206   1.1.1.7  christos 	}
    207   1.1.1.7  christos 
    208   1.1.1.3  christos 	len = 0;
    209   1.1.1.3  christos 	if (args_has(args, 'P'))
    210   1.1.1.3  christos 		buf = cmd_capture_pane_pending(args, wp, &len);
    211   1.1.1.3  christos 	else
    212   1.1.1.7  christos 		buf = cmd_capture_pane_history(args, item, wp, &len);
    213   1.1.1.3  christos 	if (buf == NULL)
    214   1.1.1.3  christos 		return (CMD_RETURN_ERROR);
    215   1.1.1.3  christos 
    216   1.1.1.3  christos 	if (args_has(args, 'p')) {
    217  1.1.1.11  christos 		if (len > 0 && buf[len - 1] == '\n')
    218  1.1.1.11  christos 			len--;
    219  1.1.1.11  christos 		if (c->flags & CLIENT_CONTROL)
    220  1.1.1.11  christos 			control_write(c, "%.*s", (int)len, buf);
    221  1.1.1.11  christos 		else {
    222  1.1.1.11  christos 			if (!file_can_print(c)) {
    223  1.1.1.11  christos 				cmdq_error(item, "can't write to client");
    224  1.1.1.11  christos 				free(buf);
    225  1.1.1.11  christos 				return (CMD_RETURN_ERROR);
    226  1.1.1.11  christos 			}
    227  1.1.1.11  christos 			file_print_buffer(c, buf, len);
    228  1.1.1.11  christos 			file_print(c, "\n");
    229   1.1.1.5  christos 			free(buf);
    230   1.1.1.3  christos 		}
    231   1.1.1.3  christos 	} else {
    232   1.1.1.5  christos 		bufname = NULL;
    233   1.1.1.5  christos 		if (args_has(args, 'b'))
    234   1.1.1.5  christos 			bufname = args_get(args, 'b');
    235   1.1.1.3  christos 
    236   1.1.1.5  christos 		if (paste_set(buf, len, bufname, &cause) != 0) {
    237   1.1.1.7  christos 			cmdq_error(item, "%s", cause);
    238   1.1.1.3  christos 			free(cause);
    239   1.1.1.3  christos 			free(buf);
    240   1.1.1.3  christos 			return (CMD_RETURN_ERROR);
    241   1.1.1.3  christos 		}
    242       1.1      jmmv 	}
    243   1.1.1.2      jmmv 
    244   1.1.1.3  christos 	return (CMD_RETURN_NORMAL);
    245       1.1      jmmv }
    246