Fix handling of short (< 4 character) checksums and a bug with parsing
[tmux-openbsd.git] / cmd-capture-pane.c
blobf3814f2fd3f58b566c4b30c8475482de40cd4937
1 /* $OpenBSD$ */
3 /*
4 * Copyright (c) 2009 Jonathan Alvarado <radobobo@users.sourceforge.net>
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.
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.
19 #include <sys/types.h>
21 #include <stdlib.h>
22 #include <string.h>
24 #include "tmux.h"
27 * Write the entire contents of a pane to a buffer or stdout.
30 enum cmd_retval cmd_capture_pane_exec(struct cmd *, struct cmd_q *);
32 const struct cmd_entry cmd_capture_pane_entry = {
33 "capture-pane", "capturep",
34 "ab:CeE:JpqS:t:", 0, 0,
35 "[-aCeJpq] [-b buffer-index] [-E end-line] [-S start-line]"
36 CMD_TARGET_PANE_USAGE,
38 NULL,
39 NULL,
40 cmd_capture_pane_exec
43 enum cmd_retval
44 cmd_capture_pane_exec(struct cmd *self, struct cmd_q *cmdq)
46 struct args *args = self->args;
47 struct client *c;
48 struct window_pane *wp;
49 char *buf, *line, *cause;
50 struct screen *s;
51 struct grid *gd;
52 int buffer, n, with_codes, escape_c0, join_lines;
53 u_int i, limit, top, bottom, tmp, sx;
54 size_t len, linelen;
55 struct grid_cell *gc;
56 const struct grid_line *gl;
58 if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL)
59 return (CMD_RETURN_ERROR);
61 if (args_has(args, 'a')) {
62 s = NULL;
63 gd = wp->saved_grid;
64 sx = screen_size_x(&wp->base);
65 if (gd == NULL && !args_has(args, 'q')) {
66 cmdq_error(cmdq, "no alternate screen");
67 return (CMD_RETURN_ERROR);
69 } else {
70 s = &wp->base;
71 sx = screen_size_x(s);
72 gd = s->grid;
75 buf = NULL;
76 len = 0;
78 if (gd != NULL) {
79 n = args_strtonum(args, 'S', INT_MIN, SHRT_MAX, &cause);
80 if (cause != NULL) {
81 top = gd->hsize;
82 free(cause);
83 } else if (n < 0 && (u_int) -n > gd->hsize)
84 top = 0;
85 else
86 top = gd->hsize + n;
87 if (top > gd->hsize + gd->sy - 1)
88 top = gd->hsize + gd->sy - 1;
90 n = args_strtonum(args, 'E', INT_MIN, SHRT_MAX, &cause);
91 if (cause != NULL) {
92 bottom = gd->hsize + gd->sy - 1;
93 free(cause);
94 } else if (n < 0 && (u_int) -n > gd->hsize)
95 bottom = 0;
96 else
97 bottom = gd->hsize + n;
98 if (bottom > gd->hsize + gd->sy - 1)
99 bottom = gd->hsize + gd->sy - 1;
101 if (bottom < top) {
102 tmp = bottom;
103 bottom = top;
104 top = tmp;
107 with_codes = args_has(args, 'e');
108 escape_c0 = args_has(args, 'C');
109 join_lines = args_has(args, 'J');
111 gc = NULL;
112 for (i = top; i <= bottom; i++) {
113 line = grid_string_cells(gd, 0, i, sx, &gc, with_codes,
114 escape_c0, !join_lines);
115 linelen = strlen(line);
117 buf = xrealloc(buf, 1, len + linelen + 1);
118 memcpy(buf + len, line, linelen);
119 len += linelen;
121 gl = grid_peek_line(gd, i);
122 if (!join_lines || !(gl->flags & GRID_LINE_WRAPPED))
123 buf[len++] = '\n';
125 free(line);
127 } else
128 buf = xstrdup("");
130 if (args_has(args, 'p')) {
131 c = cmdq->client;
132 if (c == NULL ||
133 (c->session != NULL && !(c->flags & CLIENT_CONTROL))) {
134 cmdq_error(cmdq, "can't write to stdout");
135 return (CMD_RETURN_ERROR);
137 evbuffer_add(c->stdout_data, buf, len);
138 server_push_stdout(c);
139 } else {
140 limit = options_get_number(&global_options, "buffer-limit");
141 if (!args_has(args, 'b')) {
142 paste_add(&global_buffers, buf, len, limit);
143 return (CMD_RETURN_NORMAL);
146 buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause);
147 if (cause != NULL) {
148 cmdq_error(cmdq, "buffer %s", cause);
149 free(buf);
150 free(cause);
151 return (CMD_RETURN_ERROR);
154 if (paste_replace(&global_buffers, buffer, buf, len) != 0) {
155 cmdq_error(cmdq, "no buffer %d", buffer);
156 free(buf);
157 return (CMD_RETURN_ERROR);
161 return (CMD_RETURN_NORMAL);