tmux  3.2a
About: tmux is a terminal multiplexer that lets you switch easily between several programs in one terminal.
  Fossies Dox: tmux-3.2a.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

cmd-capture-pane.c
Go to the documentation of this file.
1 /* $OpenBSD$ */
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 
21 #include <stdlib.h>
22 #include <string.h>
23 
24 #include "tmux.h"
25 
26 /*
27  * Write the entire contents of a pane to a buffer or stdout.
28  */
29 
30 static enum cmd_retval cmd_capture_pane_exec(struct cmd *, struct cmdq_item *);
31 
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 *);
37 
38 const struct cmd_entry cmd_capture_pane_entry = {
39  .name = "capture-pane",
40  .alias = "capturep",
41 
42  .args = { "ab:CeE:JNpPqS:t:", 0, 0 },
43  .usage = "[-aCeJNpPq] " CMD_BUFFER_USAGE " [-E end-line] "
44  "[-S start-line] " CMD_TARGET_PANE_USAGE,
45 
46  .target = { 't', CMD_FIND_PANE, 0 },
47 
48  .flags = CMD_AFTERHOOK,
49  .exec = cmd_capture_pane_exec
50 };
51 
52 const struct cmd_entry cmd_clear_history_entry = {
53  .name = "clear-history",
54  .alias = "clearhist",
55 
56  .args = { "t:", 0, 0 },
57  .usage = CMD_TARGET_PANE_USAGE,
58 
59  .target = { 't', CMD_FIND_PANE, 0 },
60 
61  .flags = CMD_AFTERHOOK,
62  .exec = cmd_capture_pane_exec
63 };
64 
65 static char *
66 cmd_capture_pane_append(char *buf, size_t *len, char *line, size_t linelen)
67 {
68  buf = xrealloc(buf, *len + linelen + 1);
69  memcpy(buf + *len, line, linelen);
70  *len += linelen;
71  return (buf);
72 }
73 
74 static char *
76  size_t *len)
77 {
78  struct evbuffer *pending;
79  char *buf, *line, tmp[5];
80  size_t linelen;
81  u_int i;
82 
83  pending = input_pending(wp->ictx);
84  if (pending == NULL)
85  return (xstrdup(""));
86 
87  line = EVBUFFER_DATA(pending);
88  linelen = EVBUFFER_LENGTH(pending);
89 
90  buf = xstrdup("");
91  if (args_has(args, 'C')) {
92  for (i = 0; i < linelen; i++) {
93  if (line[i] >= ' ' && line[i] != '\\') {
94  tmp[0] = line[i];
95  tmp[1] = '\0';
96  } else
97  xsnprintf(tmp, sizeof tmp, "\\%03hho", line[i]);
98  buf = cmd_capture_pane_append(buf, len, tmp,
99  strlen(tmp));
100  }
101  } else
102  buf = cmd_capture_pane_append(buf, len, line, linelen);
103  return (buf);
104 }
105 
106 static char *
108  struct window_pane *wp, size_t *len)
109 {
110  struct grid *gd;
111  const struct grid_line *gl;
112  struct grid_cell *gc = NULL;
113  int n, with_codes, escape_c0, join_lines, no_trim;
114  u_int i, sx, top, bottom, tmp;
115  char *cause, *buf, *line;
116  const char *Sflag, *Eflag;
117  size_t linelen;
118 
119  sx = screen_size_x(&wp->base);
120  if (args_has(args, 'a')) {
121  gd = wp->base.saved_grid;
122  if (gd == NULL) {
123  if (!args_has(args, 'q')) {
124  cmdq_error(item, "no alternate screen");
125  return (NULL);
126  }
127  return (xstrdup(""));
128  }
129  } else
130  gd = wp->base.grid;
131 
132  Sflag = args_get(args, 'S');
133  if (Sflag != NULL && strcmp(Sflag, "-") == 0)
134  top = 0;
135  else {
136  n = args_strtonum(args, 'S', INT_MIN, SHRT_MAX, &cause);
137  if (cause != NULL) {
138  top = gd->hsize;
139  free(cause);
140  } else if (n < 0 && (u_int) -n > gd->hsize)
141  top = 0;
142  else
143  top = gd->hsize + n;
144  if (top > gd->hsize + gd->sy - 1)
145  top = gd->hsize + gd->sy - 1;
146  }
147 
148  Eflag = args_get(args, 'E');
149  if (Eflag != NULL && strcmp(Eflag, "-") == 0)
150  bottom = gd->hsize + gd->sy - 1;
151  else {
152  n = args_strtonum(args, 'E', INT_MIN, SHRT_MAX, &cause);
153  if (cause != NULL) {
154  bottom = gd->hsize + gd->sy - 1;
155  free(cause);
156  } else if (n < 0 && (u_int) -n > gd->hsize)
157  bottom = 0;
158  else
159  bottom = gd->hsize + n;
160  if (bottom > gd->hsize + gd->sy - 1)
161  bottom = gd->hsize + gd->sy - 1;
162  }
163 
164  if (bottom < top) {
165  tmp = bottom;
166  bottom = top;
167  top = tmp;
168  }
169 
170  with_codes = args_has(args, 'e');
171  escape_c0 = args_has(args, 'C');
172  join_lines = args_has(args, 'J');
173  no_trim = args_has(args, 'N');
174 
175  buf = NULL;
176  for (i = top; i <= bottom; i++) {
177  line = grid_string_cells(gd, 0, i, sx, &gc, with_codes,
178  escape_c0, !join_lines && !no_trim);
179  linelen = strlen(line);
180 
181  buf = cmd_capture_pane_append(buf, len, line, linelen);
182 
183  gl = grid_peek_line(gd, i);
184  if (!join_lines || !(gl->flags & GRID_LINE_WRAPPED))
185  buf[(*len)++] = '\n';
186 
187  free(line);
188  }
189  return (buf);
190 }
191 
192 static enum cmd_retval
193 cmd_capture_pane_exec(struct cmd *self, struct cmdq_item *item)
194 {
195  struct args *args = cmd_get_args(self);
196  struct client *c = cmdq_get_client(item);
197  struct window_pane *wp = cmdq_get_target(item)->wp;
198  char *buf, *cause;
199  const char *bufname;
200  size_t len;
201 
202  if (cmd_get_entry(self) == &cmd_clear_history_entry) {
205  return (CMD_RETURN_NORMAL);
206  }
207 
208  len = 0;
209  if (args_has(args, 'P'))
210  buf = cmd_capture_pane_pending(args, wp, &len);
211  else
212  buf = cmd_capture_pane_history(args, item, wp, &len);
213  if (buf == NULL)
214  return (CMD_RETURN_ERROR);
215 
216  if (args_has(args, 'p')) {
217  if (len > 0 && buf[len - 1] == '\n')
218  len--;
219  if (c->flags & CLIENT_CONTROL)
220  control_write(c, "%.*s", (int)len, buf);
221  else {
222  if (!file_can_print(c)) {
223  cmdq_error(item, "can't write to client");
224  free(buf);
225  return (CMD_RETURN_ERROR);
226  }
227  file_print_buffer(c, buf, len);
228  file_print(c, "\n");
229  free(buf);
230  }
231  } else {
232  bufname = NULL;
233  if (args_has(args, 'b'))
234  bufname = args_get(args, 'b');
235 
236  if (paste_set(buf, len, bufname, &cause) != 0) {
237  cmdq_error(item, "%s", cause);
238  free(cause);
239  free(buf);
240  return (CMD_RETURN_ERROR);
241  }
242  }
243 
244  return (CMD_RETURN_NORMAL);
245 }
int args_has(struct args *args, u_char flag)
Definition: arguments.c:259
const char * args_get(struct args *args, u_char flag)
Definition: arguments.c:295
long long args_strtonum(struct args *args, u_char flag, long long minval, long long maxval, char **cause)
Definition: arguments.c:355
const struct cmd_entry cmd_clear_history_entry
static char * cmd_capture_pane_pending(struct args *, struct window_pane *, size_t *)
static char * cmd_capture_pane_history(struct args *, struct cmdq_item *, struct window_pane *, size_t *)
const struct cmd_entry cmd_capture_pane_entry
static enum cmd_retval cmd_capture_pane_exec(struct cmd *, struct cmdq_item *)
static char * cmd_capture_pane_append(char *, size_t *, char *, size_t)
struct client * cmdq_get_client(struct cmdq_item *item)
Definition: cmd-queue.c:150
struct cmd_find_state * cmdq_get_target(struct cmdq_item *item)
Definition: cmd-queue.c:171
void cmdq_error(struct cmdq_item *item, const char *fmt,...)
Definition: cmd-queue.c:833
struct args * cmd_get_args(struct cmd *cmd)
Definition: cmd.c:393
const struct cmd_entry * cmd_get_entry(struct cmd *cmd)
Definition: cmd.c:386
void control_write(struct client *c, const char *fmt,...)
Definition: control.c:406
int file_can_print(struct client *c)
Definition: file.c:174
void file_print(struct client *c, const char *fmt,...)
Definition: file.c:185
void file_print_buffer(struct client *c, void *data, size_t size)
Definition: file.c:223
void grid_clear_history(struct grid *gd)
Definition: grid.c:407
char * grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx, struct grid_cell **lastgc, int with_codes, int escape_c0, int trim)
Definition: grid.c:954
const struct grid_line * grid_peek_line(struct grid *gd, u_int py)
Definition: grid.c:486
struct evbuffer * input_pending(struct input_ctx *ictx)
Definition: input.c:868
int paste_set(char *data, size_t size, const char *name, char **cause)
Definition: paste.c:256
Definition: tmux.h:1435
Definition: tmux.h:1608
uint64_t flags
Definition: tmux.h:1703
Definition: tmux.h:1525
const char * name
Definition: tmux.h:1526
struct window_pane * wp
Definition: tmux.h:1454
Definition: cmd.c:212
int flags
Definition: tmux.h:730
Definition: tmux.h:734
u_int hsize
Definition: tmux.h:742
u_int sy
Definition: tmux.h:739
struct grid * saved_grid
Definition: tmux.h:836
struct grid * grid
Definition: tmux.h:821
struct input_ctx * ictx
Definition: tmux.h:1010
struct screen base
Definition: tmux.h:1021
cmd_retval
Definition: tmux.h:1475
@ CMD_RETURN_NORMAL
Definition: tmux.h:1477
@ CMD_RETURN_ERROR
Definition: tmux.h:1476
#define CMD_AFTERHOOK
Definition: tmux.h:1541
#define CMD_TARGET_PANE_USAGE
Definition: tmux.h:1858
#define CLIENT_CONTROL
Definition: tmux.h:1667
#define screen_size_x(s)
Definition: tmux.h:881
#define GRID_LINE_WRAPPED
Definition: tmux.h:683
#define CMD_BUFFER_USAGE
Definition: tmux.h:1866
@ CMD_FIND_PANE
Definition: tmux.h:1443
void window_pane_reset_mode_all(struct window_pane *)
Definition: window.c:1135
int xsnprintf(char *str, size_t len, const char *fmt,...)
Definition: xmalloc.c:135
void * xrealloc(void *ptr, size_t size)
Definition: xmalloc.c:55
char * xstrdup(const char *str)
Definition: xmalloc.c:89