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