static char * cmd_capture_pane_history(struct args *args, struct cmd_q *cmdq, struct window_pane *wp, size_t *len) { struct grid *gd; const struct grid_line *gl; struct grid_cell *gc = NULL; int n, with_codes, escape_c0, join_lines; u_int i, sx, top, bottom, tmp; char *cause, *buf, *line; const char *Sflag, *Eflag; size_t linelen; sx = screen_size_x(&wp->base); if (args_has(args, 'a')) { gd = wp->saved_grid; if (gd == NULL) { if (!args_has(args, 'q')) { cmdq_error(cmdq, "no alternate screen"); return (NULL); } return (xstrdup("")); } } else gd = wp->base.grid; Sflag = args_get(args, 'S'); if (Sflag != NULL && strcmp(Sflag, "-") == 0) top = 0; else { n = args_strtonum(args, 'S', INT_MIN, SHRT_MAX, &cause); if (cause != NULL) { top = gd->hsize; free(cause); } else if (n < 0 && (u_int) -n > gd->hsize) top = 0; else top = gd->hsize + n; if (top > gd->hsize + gd->sy - 1) top = gd->hsize + gd->sy - 1; } Eflag = args_get(args, 'E'); if (Eflag != NULL && strcmp(Eflag, "-") == 0) bottom = gd->hsize + gd->sy - 1; else { n = args_strtonum(args, 'E', INT_MIN, SHRT_MAX, &cause); if (cause != NULL) { bottom = gd->hsize + gd->sy - 1; free(cause); } else if (n < 0 && (u_int) -n > gd->hsize) bottom = 0; else bottom = gd->hsize + n; if (bottom > gd->hsize + gd->sy - 1) bottom = gd->hsize + gd->sy - 1; } if (bottom < top) { tmp = bottom; bottom = top; top = tmp; } with_codes = args_has(args, 'e'); escape_c0 = args_has(args, 'C'); join_lines = args_has(args, 'J'); buf = NULL; for (i = top; i <= bottom; i++) { line = grid_string_cells(gd, 0, i, sx, &gc, with_codes, escape_c0, !join_lines); linelen = strlen(line); buf = cmd_capture_pane_append(buf, len, line, linelen); gl = grid_peek_line(gd, i); if (!join_lines || !(gl->flags & GRID_LINE_WRAPPED)) buf[(*len)++] = '\n'; free(line); } return (buf); }
/* Convert cells into a string. */ 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) { struct grid_cell gc; static struct grid_cell lastgc1; const char *data; char *buf, code[128]; size_t len, off, size, codelen; u_int xx; const struct grid_line *gl; if (lastgc != NULL && *lastgc == NULL) { memcpy(&lastgc1, &grid_default_cell, sizeof lastgc1); *lastgc = &lastgc1; } len = 128; buf = xmalloc(len); off = 0; gl = grid_peek_line(gd, py); for (xx = px; xx < px + nx; xx++) { if (gl == NULL || xx >= gl->cellsize) break; grid_get_cell(gd, xx, py, &gc); if (gc.flags & GRID_FLAG_PADDING) continue; if (with_codes) { grid_string_cells_code(*lastgc, &gc, code, sizeof code, escape_c0); codelen = strlen(code); memcpy(*lastgc, &gc, sizeof **lastgc); } else codelen = 0; data = gc.data.data; size = gc.data.size; if (escape_c0 && size == 1 && *data == '\\') { data = "\\\\"; size = 2; } while (len < off + size + codelen + 1) { buf = xreallocarray(buf, 2, len); len *= 2; } if (codelen != 0) { memcpy(buf + off, code, codelen); off += codelen; } memcpy(buf + off, data, size); off += size; } if (trim) { while (off > 0 && buf[off - 1] == ' ') off--; } buf[off] = '\0'; return (buf); }