Home | History | Annotate | Line # | Download | only in dist
cmd-capture-pane.c revision 1.11
      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.11       wiz 	.args = { "ab:CeE:JNpPqS:Tt:", 0, 0, NULL },
     43  1.11       wiz 	.usage = "[-aCeJNpPqT] " 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.11       wiz 	.args = { "Ht:", 0, 0, NULL },
     57  1.11       wiz 	.usage = "[-H] " 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.9  christos 	pending = input_pending(wp->ictx);
     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.11       wiz 	int			 n, join_lines, flags = 0;
    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.9  christos 		gd = wp->base.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.11       wiz 		n = args_strtonum_and_expand(args, 'S', INT_MIN, SHRT_MAX,
    137  1.11       wiz 			item, &cause);
    138   1.3  christos 		if (cause != NULL) {
    139   1.3  christos 			top = gd->hsize;
    140   1.3  christos 			free(cause);
    141   1.3  christos 		} else if (n < 0 && (u_int) -n > gd->hsize)
    142   1.3  christos 			top = 0;
    143   1.3  christos 		else
    144   1.3  christos 			top = gd->hsize + n;
    145   1.3  christos 		if (top > gd->hsize + gd->sy - 1)
    146   1.3  christos 			top = gd->hsize + gd->sy - 1;
    147   1.3  christos 	}
    148   1.2  christos 
    149   1.3  christos 	Eflag = args_get(args, 'E');
    150   1.3  christos 	if (Eflag != NULL && strcmp(Eflag, "-") == 0)
    151   1.2  christos 		bottom = gd->hsize + gd->sy - 1;
    152   1.3  christos 	else {
    153  1.11       wiz 		n = args_strtonum_and_expand(args, 'E', INT_MIN, SHRT_MAX,
    154  1.11       wiz 			item, &cause);
    155   1.3  christos 		if (cause != NULL) {
    156   1.3  christos 			bottom = gd->hsize + gd->sy - 1;
    157   1.3  christos 			free(cause);
    158   1.3  christos 		} else if (n < 0 && (u_int) -n > gd->hsize)
    159   1.3  christos 			bottom = 0;
    160   1.3  christos 		else
    161   1.3  christos 			bottom = gd->hsize + n;
    162   1.3  christos 		if (bottom > gd->hsize + gd->sy - 1)
    163   1.3  christos 			bottom = gd->hsize + gd->sy - 1;
    164   1.3  christos 	}
    165   1.2  christos 
    166   1.2  christos 	if (bottom < top) {
    167   1.2  christos 		tmp = bottom;
    168   1.2  christos 		bottom = top;
    169   1.2  christos 		top = tmp;
    170   1.2  christos 	}
    171   1.2  christos 
    172   1.2  christos 	join_lines = args_has(args, 'J');
    173  1.11       wiz 	if (args_has(args, 'e'))
    174  1.11       wiz 		flags |= GRID_STRING_WITH_SEQUENCES;
    175  1.11       wiz 	if (args_has(args, 'C'))
    176  1.11       wiz 		flags |= GRID_STRING_ESCAPE_SEQUENCES;
    177  1.11       wiz 	if (!join_lines && !args_has(args, 'T'))
    178  1.11       wiz 		flags |= GRID_STRING_EMPTY_CELLS;
    179  1.11       wiz 	if (!join_lines && !args_has(args, 'N'))
    180  1.11       wiz 		flags |= GRID_STRING_TRIM_SPACES;
    181   1.1      jmmv 
    182   1.1      jmmv 	buf = NULL;
    183   1.2  christos 	for (i = top; i <= bottom; i++) {
    184  1.11       wiz 		line = grid_string_cells(gd, 0, i, sx, &gc, flags, wp->screen);
    185   1.2  christos 		linelen = strlen(line);
    186   1.2  christos 
    187   1.2  christos 		buf = cmd_capture_pane_append(buf, len, line, linelen);
    188   1.2  christos 
    189   1.2  christos 		gl = grid_peek_line(gd, i);
    190   1.2  christos 		if (!join_lines || !(gl->flags & GRID_LINE_WRAPPED))
    191   1.2  christos 			buf[(*len)++] = '\n';
    192   1.2  christos 
    193   1.2  christos 		free(line);
    194   1.2  christos 	}
    195   1.2  christos 	return (buf);
    196   1.2  christos }
    197   1.2  christos 
    198   1.5  christos static enum cmd_retval
    199   1.5  christos cmd_capture_pane_exec(struct cmd *self, struct cmdq_item *item)
    200   1.2  christos {
    201   1.9  christos 	struct args		*args = cmd_get_args(self);
    202   1.9  christos 	struct client		*c = cmdq_get_client(item);
    203   1.9  christos 	struct window_pane	*wp = cmdq_get_target(item)->wp;
    204   1.2  christos 	char			*buf, *cause;
    205   1.3  christos 	const char		*bufname;
    206   1.2  christos 	size_t			 len;
    207   1.1      jmmv 
    208   1.9  christos 	if (cmd_get_entry(self) == &cmd_clear_history_entry) {
    209   1.7  christos 		window_pane_reset_mode_all(wp);
    210   1.5  christos 		grid_clear_history(wp->base.grid);
    211  1.11       wiz 		if (args_has(args, 'H'))
    212  1.11       wiz 			screen_reset_hyperlinks(wp->screen);
    213   1.5  christos 		return (CMD_RETURN_NORMAL);
    214   1.5  christos 	}
    215   1.5  christos 
    216   1.2  christos 	len = 0;
    217   1.2  christos 	if (args_has(args, 'P'))
    218   1.2  christos 		buf = cmd_capture_pane_pending(args, wp, &len);
    219   1.2  christos 	else
    220   1.5  christos 		buf = cmd_capture_pane_history(args, item, wp, &len);
    221   1.2  christos 	if (buf == NULL)
    222   1.2  christos 		return (CMD_RETURN_ERROR);
    223   1.2  christos 
    224   1.2  christos 	if (args_has(args, 'p')) {
    225   1.9  christos 		if (len > 0 && buf[len - 1] == '\n')
    226   1.9  christos 			len--;
    227   1.9  christos 		if (c->flags & CLIENT_CONTROL)
    228   1.9  christos 			control_write(c, "%.*s", (int)len, buf);
    229   1.9  christos 		else {
    230   1.9  christos 			if (!file_can_print(c)) {
    231   1.9  christos 				cmdq_error(item, "can't write to client");
    232   1.9  christos 				free(buf);
    233   1.9  christos 				return (CMD_RETURN_ERROR);
    234   1.9  christos 			}
    235   1.9  christos 			file_print_buffer(c, buf, len);
    236   1.9  christos 			file_print(c, "\n");
    237   1.3  christos 			free(buf);
    238   1.2  christos 		}
    239   1.2  christos 	} else {
    240   1.3  christos 		bufname = NULL;
    241   1.3  christos 		if (args_has(args, 'b'))
    242   1.3  christos 			bufname = args_get(args, 'b');
    243   1.2  christos 
    244   1.3  christos 		if (paste_set(buf, len, bufname, &cause) != 0) {
    245   1.5  christos 			cmdq_error(item, "%s", cause);
    246   1.2  christos 			free(cause);
    247   1.2  christos 			free(buf);
    248   1.2  christos 			return (CMD_RETURN_ERROR);
    249   1.2  christos 		}
    250   1.1      jmmv 	}
    251   1.1      jmmv 
    252   1.2  christos 	return (CMD_RETURN_NORMAL);
    253   1.1      jmmv }
    254