|
|
|
|
@@ -82,6 +82,9 @@ static void window_copy_write_line(struct window_mode_entry *,
|
|
|
|
|
struct screen_write_ctx *, u_int);
|
|
|
|
|
static void window_copy_write_lines(struct window_mode_entry *,
|
|
|
|
|
struct screen_write_ctx *, u_int, u_int);
|
|
|
|
|
static void window_copy_write_gutter(struct window_mode_entry *,
|
|
|
|
|
struct screen_write_ctx *, u_int, u_int,
|
|
|
|
|
const struct grid_cell *);
|
|
|
|
|
static void window_copy_rebuild_backing(struct window_mode_entry *);
|
|
|
|
|
static int window_copy_set_fold(struct window_mode_entry *,
|
|
|
|
|
const struct window_copy_fold_request *);
|
|
|
|
|
@@ -293,10 +296,10 @@ enum window_copy_fold_action {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct window_copy_fold_request {
|
|
|
|
|
enum window_copy_fold_action action;
|
|
|
|
|
int all;
|
|
|
|
|
u_int target;
|
|
|
|
|
int command_end;
|
|
|
|
|
enum window_copy_fold_action action;
|
|
|
|
|
int all;
|
|
|
|
|
u_int target;
|
|
|
|
|
int command_end;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* State carried across source lines while rebuilding the folded screen. */
|
|
|
|
|
@@ -335,12 +338,12 @@ struct window_copy_line {
|
|
|
|
|
* structure (which is deallocated when the mode ends).
|
|
|
|
|
*/
|
|
|
|
|
struct window_copy_mode_data {
|
|
|
|
|
struct screen screen;
|
|
|
|
|
struct screen screen;
|
|
|
|
|
|
|
|
|
|
struct screen *backing;
|
|
|
|
|
struct screen *source;
|
|
|
|
|
u_char *source_flags; /* Flags per source line */
|
|
|
|
|
u_int source_line_count;
|
|
|
|
|
struct screen *backing;
|
|
|
|
|
struct screen *source;
|
|
|
|
|
u_char *source_flags; /* flags per source line */
|
|
|
|
|
u_int source_line_count;
|
|
|
|
|
struct window_copy_line *lines;
|
|
|
|
|
u_int line_count;
|
|
|
|
|
int backing_written; /* backing display started */
|
|
|
|
|
@@ -560,6 +563,8 @@ window_copy_set_control(struct window_copy_mode_data *data, u_int y,
|
|
|
|
|
line->flags |= WINDOW_COPY_LINE_CONTROL;
|
|
|
|
|
if (expandable)
|
|
|
|
|
line->flags |= WINDOW_COPY_LINE_EXPANDABLE;
|
|
|
|
|
else
|
|
|
|
|
line->flags &= ~WINDOW_COPY_LINE_EXPANDABLE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
@@ -583,10 +588,7 @@ window_copy_expand_exit_status(struct window_mode_entry *wme,
|
|
|
|
|
const char *value;
|
|
|
|
|
char *expanded;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This is called while rebuilding the backing grid, before the copy
|
|
|
|
|
* cursor and viewport have been restored for the new grid.
|
|
|
|
|
*/
|
|
|
|
|
/* The copy cursor and viewport have not been restored yet. */
|
|
|
|
|
ft = format_create(NULL, NULL, 0, 0);
|
|
|
|
|
format_add(ft, "exit_status", "0");
|
|
|
|
|
format_add(ft, "exit_status_present", "0");
|
|
|
|
|
@@ -594,7 +596,7 @@ window_copy_expand_exit_status(struct window_mode_entry *wme,
|
|
|
|
|
format_add(ft, "exit_status", "%hhu", line->exit_status);
|
|
|
|
|
format_add(ft, "exit_status_present", "1");
|
|
|
|
|
}
|
|
|
|
|
value = options_get_string(wme->wp->window->options,
|
|
|
|
|
value = options_get_string(wme->wp->options,
|
|
|
|
|
"copy-mode-exit-status-format");
|
|
|
|
|
expanded = format_expand(ft, value);
|
|
|
|
|
format_free(ft);
|
|
|
|
|
@@ -607,7 +609,7 @@ window_copy_update_exit_status_width(struct window_mode_entry *wme)
|
|
|
|
|
struct window_copy_mode_data *data = wme->data;
|
|
|
|
|
struct window_copy_line *line;
|
|
|
|
|
char *expanded;
|
|
|
|
|
u_int width, y;
|
|
|
|
|
u_int width, length, y;
|
|
|
|
|
|
|
|
|
|
data->output_status_width = 0;
|
|
|
|
|
if (!data->fold_view || data->lines == NULL)
|
|
|
|
|
@@ -618,8 +620,9 @@ window_copy_update_exit_status_width(struct window_mode_entry *wme)
|
|
|
|
|
if (~line->flags & WINDOW_COPY_LINE_CONTROL)
|
|
|
|
|
continue;
|
|
|
|
|
expanded = window_copy_expand_exit_status(wme, line);
|
|
|
|
|
if (format_width(expanded) > width)
|
|
|
|
|
width = format_width(expanded);
|
|
|
|
|
length = format_width(expanded);
|
|
|
|
|
if (length > width)
|
|
|
|
|
width = length;
|
|
|
|
|
free(expanded);
|
|
|
|
|
}
|
|
|
|
|
data->output_status_width = width;
|
|
|
|
|
@@ -638,6 +641,19 @@ window_copy_set_source_folded(struct window_copy_mode_data *data, u_int y,
|
|
|
|
|
return (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Find the first primary prompt, if any. */
|
|
|
|
|
static u_int
|
|
|
|
|
window_copy_first_prompt(struct grid *gd)
|
|
|
|
|
{
|
|
|
|
|
u_int y, total = gd->hsize + gd->sy;
|
|
|
|
|
|
|
|
|
|
for (y = 0; y < total; y++) {
|
|
|
|
|
if (grid_get_line(gd, y)->flags & GRID_LINE_START_PROMPT)
|
|
|
|
|
return (y);
|
|
|
|
|
}
|
|
|
|
|
return (UINT_MAX);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
window_copy_any_fold_collapsed(struct window_copy_mode_data *data)
|
|
|
|
|
{
|
|
|
|
|
@@ -646,14 +662,10 @@ window_copy_any_fold_collapsed(struct window_copy_mode_data *data)
|
|
|
|
|
u_int y;
|
|
|
|
|
int command = 0, output = 0;
|
|
|
|
|
|
|
|
|
|
for (y = 0; y < gd->hsize + gd->sy; y++) {
|
|
|
|
|
gl = grid_get_line(gd, y);
|
|
|
|
|
if (gl->flags & GRID_LINE_START_PROMPT)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (y != 0 && y != gd->hsize + gd->sy &&
|
|
|
|
|
y = window_copy_first_prompt(gd);
|
|
|
|
|
if (y != 0 && y != UINT_MAX &&
|
|
|
|
|
(data->source_flags[0] & WINDOW_COPY_FOLD_COLLAPSED))
|
|
|
|
|
/* Output which has scrolled off top of buffer is collapsed. */
|
|
|
|
|
/* The initial output region is collapsed. */
|
|
|
|
|
return (1);
|
|
|
|
|
|
|
|
|
|
for (y = 0; y < gd->hsize + gd->sy; y++) {
|
|
|
|
|
@@ -671,7 +683,8 @@ window_copy_any_fold_collapsed(struct window_copy_mode_data *data)
|
|
|
|
|
}
|
|
|
|
|
if (gl->flags & GRID_LINE_END_OUTPUT) {
|
|
|
|
|
if (!output && command &&
|
|
|
|
|
(data->source_flags[y] & WINDOW_COPY_FOLD_COLLAPSED))
|
|
|
|
|
(data->source_flags[y] &
|
|
|
|
|
WINDOW_COPY_FOLD_COLLAPSED))
|
|
|
|
|
return (1);
|
|
|
|
|
command = output = 0;
|
|
|
|
|
}
|
|
|
|
|
@@ -687,15 +700,10 @@ window_copy_set_all_folds(struct window_copy_mode_data *data, int collapse)
|
|
|
|
|
u_int y;
|
|
|
|
|
int changed = 0, command = 0, output = 0;
|
|
|
|
|
|
|
|
|
|
for (y = 0; y < gd->hsize + gd->sy; y++) {
|
|
|
|
|
gl = grid_get_line(gd, y);
|
|
|
|
|
if (gl->flags & GRID_LINE_START_PROMPT)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (y != 0 && y != gd->hsize + gd->sy &&
|
|
|
|
|
window_copy_set_source_folded(data, 0, collapse)) {
|
|
|
|
|
y = window_copy_first_prompt(gd);
|
|
|
|
|
if (y != 0 && y != UINT_MAX &&
|
|
|
|
|
window_copy_set_source_folded(data, 0, collapse))
|
|
|
|
|
changed = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (y = 0; y < gd->hsize + gd->sy; y++) {
|
|
|
|
|
gl = grid_get_line(gd, y);
|
|
|
|
|
@@ -706,16 +714,14 @@ window_copy_set_all_folds(struct window_copy_mode_data *data, int collapse)
|
|
|
|
|
if (gl->flags & GRID_LINE_START_COMMAND)
|
|
|
|
|
command = 1;
|
|
|
|
|
if (gl->flags & GRID_LINE_START_OUTPUT) {
|
|
|
|
|
if (window_copy_set_source_folded(data, y, collapse)) {
|
|
|
|
|
if (window_copy_set_source_folded(data, y, collapse))
|
|
|
|
|
changed = 1;
|
|
|
|
|
}
|
|
|
|
|
output = 1;
|
|
|
|
|
}
|
|
|
|
|
if (gl->flags & GRID_LINE_END_OUTPUT) {
|
|
|
|
|
if (!output && command &&
|
|
|
|
|
window_copy_set_source_folded(data, y, collapse)) {
|
|
|
|
|
window_copy_set_source_folded(data, y, collapse))
|
|
|
|
|
changed = 1;
|
|
|
|
|
}
|
|
|
|
|
command = output = 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@@ -730,7 +736,6 @@ window_copy_rebuild_backing(struct window_mode_entry *wme)
|
|
|
|
|
struct screen *src = data->source, *dst;
|
|
|
|
|
struct grid *sgd;
|
|
|
|
|
struct grid_line *sgl, *dgl;
|
|
|
|
|
struct window_copy_line *line;
|
|
|
|
|
struct screen_write_ctx ctx;
|
|
|
|
|
struct grid_cell gc;
|
|
|
|
|
struct osc133_data *osc133;
|
|
|
|
|
@@ -744,7 +749,8 @@ window_copy_rebuild_backing(struct window_mode_entry *wme)
|
|
|
|
|
if (src == NULL)
|
|
|
|
|
return;
|
|
|
|
|
if (!data->fold_view) {
|
|
|
|
|
dst = window_copy_clone_screen(src, &data->screen, NULL, NULL, 0);
|
|
|
|
|
dst = window_copy_clone_screen(src, &data->screen, NULL, NULL,
|
|
|
|
|
0);
|
|
|
|
|
if (data->backing != NULL) {
|
|
|
|
|
screen_free(data->backing);
|
|
|
|
|
free(data->backing);
|
|
|
|
|
@@ -759,8 +765,8 @@ window_copy_rebuild_backing(struct window_mode_entry *wme)
|
|
|
|
|
sgd = src->grid;
|
|
|
|
|
total = sgd->hsize + sgd->sy;
|
|
|
|
|
dst = xcalloc(1, sizeof *dst);
|
|
|
|
|
screen_init(dst, screen_size_x(&data->screen), screen_size_y(&data->screen),
|
|
|
|
|
screen_hlimit(src));
|
|
|
|
|
screen_init(dst, screen_size_x(&data->screen),
|
|
|
|
|
screen_size_y(&data->screen), screen_hlimit(src));
|
|
|
|
|
dst->grid->flags |= GRID_HISTORY;
|
|
|
|
|
free(data->lines);
|
|
|
|
|
data->lines = xcalloc(total, sizeof *data->lines);
|
|
|
|
|
@@ -769,24 +775,12 @@ window_copy_rebuild_backing(struct window_mode_entry *wme)
|
|
|
|
|
data->lines[y].source_line = UINT_MAX;
|
|
|
|
|
data->lines[y].output_line = UINT_MAX;
|
|
|
|
|
}
|
|
|
|
|
for (y = 0; y < total; y++) {
|
|
|
|
|
sgl = grid_get_line(sgd, y);
|
|
|
|
|
if (sgl->flags & GRID_LINE_START_PROMPT)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (y != 0 && y != total)
|
|
|
|
|
/*
|
|
|
|
|
* The source begins in an existing command or its output. Treat its
|
|
|
|
|
* first line as a synthetic command for the region before the first A.
|
|
|
|
|
*/
|
|
|
|
|
fold.initial = 1;
|
|
|
|
|
y = window_copy_first_prompt(sgd);
|
|
|
|
|
/* Keep the first line as the control for any initial output. */
|
|
|
|
|
fold.initial = (y != 0 && y != UINT_MAX);
|
|
|
|
|
|
|
|
|
|
screen_write_start(&ctx, dst);
|
|
|
|
|
/*
|
|
|
|
|
* Markers may occur at any column, so copy the source one cell boundary at
|
|
|
|
|
* a time. The final boundary (cellused) is included to handle a marker
|
|
|
|
|
* immediately after the last cell on a line.
|
|
|
|
|
*/
|
|
|
|
|
/* Include the final cell boundary for markers after the last cell. */
|
|
|
|
|
for (y = 0; y < total; y++) {
|
|
|
|
|
sgl = grid_get_line(sgd, y);
|
|
|
|
|
osc133 = &sgl->osc133_data;
|
|
|
|
|
@@ -794,124 +788,81 @@ window_copy_rebuild_backing(struct window_mode_entry *wme)
|
|
|
|
|
dy = dst->grid->hsize + dst->cy;
|
|
|
|
|
was_hiding = fold.hiding;
|
|
|
|
|
if (!fold.hiding)
|
|
|
|
|
/*
|
|
|
|
|
* Row is visible. Records the source
|
|
|
|
|
* row and current output-block identity
|
|
|
|
|
* for cursor restoration, selection,
|
|
|
|
|
* gutter drawing, and line numbers.
|
|
|
|
|
*/
|
|
|
|
|
/* Map visible rows to their source. */
|
|
|
|
|
window_copy_set_line(data, dy, y,
|
|
|
|
|
fold.output_line, 0);
|
|
|
|
|
/*
|
|
|
|
|
* Continue even if row is folded because
|
|
|
|
|
* there may be markers to process.
|
|
|
|
|
*/
|
|
|
|
|
/* Process markers on hidden rows too. */
|
|
|
|
|
dgl = grid_get_line(dst->grid, dy);
|
|
|
|
|
if (fold.initial && y == 0 && x == 0)
|
|
|
|
|
/* Top line of buffer, no osc133 marker yet.
|
|
|
|
|
* Attach controls to top line, make it a
|
|
|
|
|
* "synthetic command" so top lines can fold.
|
|
|
|
|
*/
|
|
|
|
|
/* Attach initial output controls. */
|
|
|
|
|
window_copy_set_line(data, dy, y, UINT_MAX,
|
|
|
|
|
WINDOW_COPY_LINE_CONTROL | WINDOW_COPY_LINE_INITIAL);
|
|
|
|
|
WINDOW_COPY_LINE_CONTROL|
|
|
|
|
|
WINDOW_COPY_LINE_INITIAL);
|
|
|
|
|
if ((sgl->flags & GRID_LINE_START_OUTPUT) &&
|
|
|
|
|
x == osc133->out_start_col) {
|
|
|
|
|
/*
|
|
|
|
|
* osc133 C starts the collapsible region
|
|
|
|
|
* controlled by this source line.
|
|
|
|
|
*/
|
|
|
|
|
/* C starts the collapsible output region. */
|
|
|
|
|
dgl->flags |= GRID_LINE_START_OUTPUT;
|
|
|
|
|
dgl->osc133_data.out_start_col = dst->cx;
|
|
|
|
|
fold.output_line = y;
|
|
|
|
|
/* used to draw the | or L in gutter */
|
|
|
|
|
fold.tree = 1;
|
|
|
|
|
fold.in_output = 1;
|
|
|
|
|
fold.output_empty = 1;
|
|
|
|
|
fold.collapsed = data->source_flags[y] &
|
|
|
|
|
WINDOW_COPY_FOLD_COLLAPSED;
|
|
|
|
|
/* Start/stop hiding cells */
|
|
|
|
|
fold.hiding = fold.collapsed;
|
|
|
|
|
if (fold.prompt_dy != UINT_MAX)
|
|
|
|
|
/* Attach +/- controls to the prompt. */
|
|
|
|
|
window_copy_set_control(data,
|
|
|
|
|
fold.prompt_dy, fold.output_line, 1);
|
|
|
|
|
fold.prompt_dy,
|
|
|
|
|
fold.output_line, 1);
|
|
|
|
|
}
|
|
|
|
|
if ((sgl->flags & GRID_LINE_END_OUTPUT) &&
|
|
|
|
|
x == osc133->out_end_col) {
|
|
|
|
|
/*
|
|
|
|
|
* Command output ends at the osc133 D
|
|
|
|
|
* marker. There may be more lines
|
|
|
|
|
* (like pre-prompt output) before next A
|
|
|
|
|
* marker. Fold these with previous output
|
|
|
|
|
* until the following A marker.
|
|
|
|
|
*/
|
|
|
|
|
/* Fold text after D until the next A. */
|
|
|
|
|
dgl->flags |= GRID_LINE_END_OUTPUT;
|
|
|
|
|
if (sgl->flags & GRID_LINE_END_OUTPUT_STATUS)
|
|
|
|
|
dgl->flags |= GRID_LINE_END_OUTPUT_STATUS;
|
|
|
|
|
dgl->flags |=
|
|
|
|
|
GRID_LINE_END_OUTPUT_STATUS;
|
|
|
|
|
dgl->osc133_data.out_end_col = dst->cx;
|
|
|
|
|
dgl->osc133_data.exit_status = osc133->exit_status;
|
|
|
|
|
dgl->osc133_data.exit_status =
|
|
|
|
|
osc133->exit_status;
|
|
|
|
|
if (fold.in_output && fold.output_empty &&
|
|
|
|
|
fold.prompt_dy != UINT_MAX) {
|
|
|
|
|
line = window_copy_get_line_info(data,
|
|
|
|
|
fold.prompt_dy);
|
|
|
|
|
if (line != NULL)
|
|
|
|
|
/* No output to hide, no +/-. */
|
|
|
|
|
line->flags &= ~WINDOW_COPY_LINE_EXPANDABLE;
|
|
|
|
|
}
|
|
|
|
|
fold.prompt_dy != UINT_MAX)
|
|
|
|
|
/* No output to hide, no +/-. */
|
|
|
|
|
window_copy_set_control(data,
|
|
|
|
|
fold.prompt_dy,
|
|
|
|
|
fold.output_line, 0);
|
|
|
|
|
fold.in_output = 0;
|
|
|
|
|
if (fold.output_line == UINT_MAX &&
|
|
|
|
|
fold.command) {
|
|
|
|
|
/*
|
|
|
|
|
* Saw osc133 B but not C marker.
|
|
|
|
|
* This could be user pressed enter
|
|
|
|
|
* or command like 'true' with no
|
|
|
|
|
* output.
|
|
|
|
|
*/
|
|
|
|
|
/* B without C has no output. */
|
|
|
|
|
fold.output_line = y;
|
|
|
|
|
fold.tree = 1;
|
|
|
|
|
/* Block is collapsed? */
|
|
|
|
|
fold.collapsed = data->source_flags[y] &
|
|
|
|
|
WINDOW_COPY_FOLD_COLLAPSED;
|
|
|
|
|
if (fold.prompt_dy != UINT_MAX)
|
|
|
|
|
/*
|
|
|
|
|
* Make this a +/- control row
|
|
|
|
|
* but without the +/- for now
|
|
|
|
|
* since we don't know what
|
|
|
|
|
* comes below.
|
|
|
|
|
*/
|
|
|
|
|
/* Show output controls. */
|
|
|
|
|
window_copy_set_control(data,
|
|
|
|
|
fold.prompt_dy,
|
|
|
|
|
fold.output_line, 0);
|
|
|
|
|
}
|
|
|
|
|
if (fold.prompt_dy != UINT_MAX &&
|
|
|
|
|
sgl->flags & GRID_LINE_END_OUTPUT_STATUS)
|
|
|
|
|
/*
|
|
|
|
|
* osc133 D, record exit status on the
|
|
|
|
|
* command's prompt row.
|
|
|
|
|
*/
|
|
|
|
|
window_copy_set_exit_status(data,
|
|
|
|
|
fold.prompt_dy, osc133->exit_status);
|
|
|
|
|
fold.prompt_dy,
|
|
|
|
|
osc133->exit_status);
|
|
|
|
|
if (fold.initial && fold.prompt_dy == UINT_MAX)
|
|
|
|
|
/* At top of buffer before first osc A
|
|
|
|
|
* marker use first line's fold state.
|
|
|
|
|
*/
|
|
|
|
|
/* Keep the initial fold state. */
|
|
|
|
|
fold.hiding = data->source_flags[0] &
|
|
|
|
|
WINDOW_COPY_FOLD_COLLAPSED;
|
|
|
|
|
else
|
|
|
|
|
/*
|
|
|
|
|
* Otherwise, use the current block's
|
|
|
|
|
* fold state.
|
|
|
|
|
*/
|
|
|
|
|
fold.hiding = fold.collapsed;
|
|
|
|
|
fold.command = 0;
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
* Process osc133 C and D before a following prompt
|
|
|
|
|
* at the same column.
|
|
|
|
|
*/
|
|
|
|
|
/* Process C and D before A at the same column. */
|
|
|
|
|
if ((sgl->flags & GRID_LINE_START_PROMPT) &&
|
|
|
|
|
x == osc133->prompt_col) {
|
|
|
|
|
/* osc133 A ends region, starts new prompt. */
|
|
|
|
|
/* A starts a new prompt. */
|
|
|
|
|
dgl->flags |= GRID_LINE_START_PROMPT;
|
|
|
|
|
dgl->osc133_data.prompt_col = dst->cx;
|
|
|
|
|
fold.prompt_dy = dy;
|
|
|
|
|
@@ -922,21 +873,16 @@ window_copy_rebuild_backing(struct window_mode_entry *wme)
|
|
|
|
|
}
|
|
|
|
|
if ((sgl->flags & GRID_LINE_SECOND_PROMPT) &&
|
|
|
|
|
x == osc133->prompt_col) {
|
|
|
|
|
/* osc133 A;k=s, marks secondary prompt. */
|
|
|
|
|
dgl->flags |= GRID_LINE_SECOND_PROMPT;
|
|
|
|
|
dgl->osc133_data.prompt_col = dst->cx;
|
|
|
|
|
}
|
|
|
|
|
if ((sgl->flags & GRID_LINE_START_COMMAND) &&
|
|
|
|
|
x == osc133->cmd_col) {
|
|
|
|
|
/* osc133 B marks start/continue of command. */
|
|
|
|
|
dgl->flags |= GRID_LINE_START_COMMAND;
|
|
|
|
|
dgl->osc133_data.cmd_col = dst->cx;
|
|
|
|
|
fold.command = 1;
|
|
|
|
|
}
|
|
|
|
|
/*
|
|
|
|
|
* An osc133 A may expose the remainder of this source
|
|
|
|
|
* line after a folded region.
|
|
|
|
|
*/
|
|
|
|
|
/* A may expose cells after a folded region. */
|
|
|
|
|
if (was_hiding && !fold.hiding)
|
|
|
|
|
window_copy_set_line(data, dy, y,
|
|
|
|
|
fold.output_line, 0);
|
|
|
|
|
@@ -952,40 +898,31 @@ window_copy_rebuild_backing(struct window_mode_entry *wme)
|
|
|
|
|
fold.prompt_dy != UINT_MAX)
|
|
|
|
|
window_copy_set_control(data, fold.prompt_dy,
|
|
|
|
|
fold.output_line, 1);
|
|
|
|
|
/*
|
|
|
|
|
* osc133 marker processing continues while folded, but
|
|
|
|
|
* cell output does not.
|
|
|
|
|
*/
|
|
|
|
|
/* Skip hidden cells after processing their markers. */
|
|
|
|
|
if (fold.hiding)
|
|
|
|
|
continue;
|
|
|
|
|
if (!(gc.flags & GRID_FLAG_PADDING)) {
|
|
|
|
|
screen_write_cell(&ctx, &gc);
|
|
|
|
|
if (fold.tree)
|
|
|
|
|
window_copy_set_line(data, dy, y,
|
|
|
|
|
fold.output_line, WINDOW_COPY_LINE_MEMBER);
|
|
|
|
|
fold.output_line,
|
|
|
|
|
WINDOW_COPY_LINE_MEMBER);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!fold.hiding && fold.tree && sgl->cellused == 0 &&
|
|
|
|
|
~(sgl->flags) & (GRID_LINE_START_PROMPT |
|
|
|
|
|
GRID_LINE_START_OUTPUT | GRID_LINE_END_OUTPUT))
|
|
|
|
|
/* Mark empty visible lines so gutter tree continues */
|
|
|
|
|
/* Continue the gutter tree on empty lines. */
|
|
|
|
|
window_copy_set_line(data, dy, y, fold.output_line,
|
|
|
|
|
WINDOW_COPY_LINE_MEMBER);
|
|
|
|
|
if (y + 1 != total && !(sgl->flags & GRID_LINE_WRAPPED) &&
|
|
|
|
|
(!fold.hiding || (fold.initial && y == 0))) {
|
|
|
|
|
/*
|
|
|
|
|
* Hide folded line breaks, except after the initial
|
|
|
|
|
* synthetic command line (top line of copy buffer).
|
|
|
|
|
*/
|
|
|
|
|
/* Keep the initial region's control line visible. */
|
|
|
|
|
screen_write_carriagereturn(&ctx);
|
|
|
|
|
screen_write_linefeed(&ctx, 0, 8);
|
|
|
|
|
}
|
|
|
|
|
if (fold.initial && y == 0) {
|
|
|
|
|
/*
|
|
|
|
|
* Top line of buffer (which may not be a command)
|
|
|
|
|
* becomes our "synthisied" commmand to anchor lines
|
|
|
|
|
* folded below it up to first osc133 A.
|
|
|
|
|
*/
|
|
|
|
|
/* Fold initial output below its control line. */
|
|
|
|
|
fold.tree = 1;
|
|
|
|
|
fold.hiding = data->source_flags[0] &
|
|
|
|
|
WINDOW_COPY_FOLD_COLLAPSED;
|
|
|
|
|
@@ -1029,11 +966,10 @@ window_copy_sync_backing(struct window_mode_entry *wme)
|
|
|
|
|
struct screen *src = &wp->base;
|
|
|
|
|
struct screen *dst = data->source;
|
|
|
|
|
struct grid *sg = src->grid;
|
|
|
|
|
struct grid *dg = dst->grid;
|
|
|
|
|
u_int sy = sg->sy;
|
|
|
|
|
u_int old_hsize = dg->hsize;
|
|
|
|
|
u_int new_hsize = sg->hsize;
|
|
|
|
|
u_int added, collected, kept, old_count, new_count;
|
|
|
|
|
struct grid *dg;
|
|
|
|
|
u_int sy, old_hsize, new_hsize;
|
|
|
|
|
u_int added, collected, kept;
|
|
|
|
|
u_int old_count, new_count;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Only a pane's own live grid is tracked incrementally. A different
|
|
|
|
|
@@ -1042,6 +978,10 @@ window_copy_sync_backing(struct window_mode_entry *wme)
|
|
|
|
|
*/
|
|
|
|
|
if (data->source == NULL || data->viewmode || wme->swp != wme->wp)
|
|
|
|
|
return (0);
|
|
|
|
|
dg = dst->grid;
|
|
|
|
|
sy = sg->sy;
|
|
|
|
|
old_hsize = dg->hsize;
|
|
|
|
|
new_hsize = sg->hsize;
|
|
|
|
|
|
|
|
|
|
/* Indices only line up at the same size and generation. */
|
|
|
|
|
if (sg->sx != dg->sx || sg->sy != dg->sy ||
|
|
|
|
|
@@ -1064,17 +1004,15 @@ window_copy_sync_backing(struct window_mode_entry *wme)
|
|
|
|
|
kept = old_hsize - collected;
|
|
|
|
|
old_count = old_hsize + sy;
|
|
|
|
|
new_count = new_hsize + sy;
|
|
|
|
|
if (collected != 0) {
|
|
|
|
|
if (collected != 0)
|
|
|
|
|
memmove(data->source_flags, data->source_flags + collected,
|
|
|
|
|
(old_count - collected) * sizeof *data->source_flags);
|
|
|
|
|
}
|
|
|
|
|
data->source_flags = xreallocarray(data->source_flags, new_count,
|
|
|
|
|
sizeof *data->source_flags);
|
|
|
|
|
if (new_count > old_count - collected) {
|
|
|
|
|
if (new_count > old_count - collected)
|
|
|
|
|
memset(data->source_flags + old_count - collected, 0,
|
|
|
|
|
(new_count - (old_count - collected)) *
|
|
|
|
|
sizeof *data->source_flags);
|
|
|
|
|
}
|
|
|
|
|
data->source_line_count = new_count;
|
|
|
|
|
|
|
|
|
|
if (added == 0 && collected == 0) {
|
|
|
|
|
@@ -1185,7 +1123,7 @@ window_copy_init(struct window_mode_entry *wme,
|
|
|
|
|
screen_size_y(data->source);
|
|
|
|
|
data->fold_view = args_has(args, 'c') || args_has(args, 'U');
|
|
|
|
|
if (args_has(args, 'c'))
|
|
|
|
|
window_copy_set_all_folds(data, 1);
|
|
|
|
|
window_copy_set_all_folds(data, 1);
|
|
|
|
|
window_copy_rebuild_backing(wme);
|
|
|
|
|
window_copy_sync_snapshot(data, base->grid);
|
|
|
|
|
|
|
|
|
|
@@ -1194,7 +1132,8 @@ window_copy_init(struct window_mode_entry *wme,
|
|
|
|
|
window_copy_find_fold(wme, cy, &prompt, &chosen)) {
|
|
|
|
|
restored = window_copy_restore_cursor(wme, cx, cy);
|
|
|
|
|
if (!restored)
|
|
|
|
|
restored = window_copy_restore_command_end(wme, prompt, chosen);
|
|
|
|
|
restored = window_copy_restore_command_end(wme, prompt,
|
|
|
|
|
chosen);
|
|
|
|
|
} else if (data->fold_view)
|
|
|
|
|
restored = window_copy_restore_cursor(wme, cx, cy);
|
|
|
|
|
if (!restored && cy < screen_hsize(data->backing)) {
|
|
|
|
|
@@ -2183,10 +2122,11 @@ window_copy_cmd_select_output(struct window_copy_cmd_state *cs)
|
|
|
|
|
{
|
|
|
|
|
struct window_mode_entry *wme = cs->wme;
|
|
|
|
|
struct window_copy_mode_data *data = wme->data;
|
|
|
|
|
struct window_copy_fold_request request = {
|
|
|
|
|
struct window_copy_fold_request request = {
|
|
|
|
|
.action = WINDOW_COPY_FOLD_EXPAND
|
|
|
|
|
};
|
|
|
|
|
struct grid_reader gr;
|
|
|
|
|
struct grid *gd;
|
|
|
|
|
void *buf;
|
|
|
|
|
size_t len;
|
|
|
|
|
u_int sx, sy, ex, ey, bsx, bsy, bex, bey;
|
|
|
|
|
@@ -2194,10 +2134,13 @@ window_copy_cmd_select_output(struct window_copy_cmd_state *cs)
|
|
|
|
|
int all = args_has(cs->wargs, 'a');
|
|
|
|
|
|
|
|
|
|
if (all) {
|
|
|
|
|
gd = data->backing->grid;
|
|
|
|
|
if (data->source != NULL)
|
|
|
|
|
gd = data->source->grid;
|
|
|
|
|
sx = sy = 0;
|
|
|
|
|
total = data->source->grid->hsize + data->source->grid->sy;
|
|
|
|
|
total = gd->hsize + gd->sy;
|
|
|
|
|
ey = total - 1;
|
|
|
|
|
ex = grid_get_line(data->source->grid, ey)->cellused;
|
|
|
|
|
ex = grid_get_line(gd, ey)->cellused;
|
|
|
|
|
} else if (!window_copy_find_output_range(wme, &sx, &sy, &ex, &ey))
|
|
|
|
|
return (WINDOW_COPY_CMD_NOTHING);
|
|
|
|
|
buf = window_copy_get_output(wme, &len, all);
|
|
|
|
|
@@ -4145,8 +4088,8 @@ window_copy_find_fold(struct window_mode_entry *wme, u_int target,
|
|
|
|
|
for (y = 0; y < gd->hsize + gd->sy; y++) {
|
|
|
|
|
gl = grid_get_line(gd, y);
|
|
|
|
|
if (gl->flags & GRID_LINE_START_PROMPT) {
|
|
|
|
|
if (have_prompt && target >= last_prompt && target < y &&
|
|
|
|
|
candidate != UINT_MAX) {
|
|
|
|
|
if (have_prompt && candidate != UINT_MAX &&
|
|
|
|
|
target >= last_prompt && target < y) {
|
|
|
|
|
*prompt = last_prompt;
|
|
|
|
|
*chosen = candidate;
|
|
|
|
|
return (1);
|
|
|
|
|
@@ -4194,8 +4137,7 @@ window_copy_cursor_source(struct window_mode_entry *wme, u_int *source_x,
|
|
|
|
|
else if (line->source_line == UINT_MAX) {
|
|
|
|
|
*source_x = UINT_MAX;
|
|
|
|
|
*source_y = data->source_line_count - 1;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
} else
|
|
|
|
|
*source_y = line->source_line;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -4263,7 +4205,8 @@ window_copy_restore_command_end(struct window_mode_entry *wme, u_int prompt,
|
|
|
|
|
struct grid *gd = data->backing->grid;
|
|
|
|
|
struct grid_line *gl;
|
|
|
|
|
struct window_copy_line *line;
|
|
|
|
|
u_int command_start = UINT_MAX, marker = UINT_MAX;
|
|
|
|
|
u_int command_start = UINT_MAX;
|
|
|
|
|
u_int marker = UINT_MAX;
|
|
|
|
|
u_int marker_x = 0, length, y;
|
|
|
|
|
int previous = 0;
|
|
|
|
|
|
|
|
|
|
@@ -4354,9 +4297,10 @@ window_copy_set_fold(struct window_mode_entry *wme,
|
|
|
|
|
{
|
|
|
|
|
struct window_copy_mode_data *data = wme->data;
|
|
|
|
|
u_int prompt = 0, source_x, source_y;
|
|
|
|
|
u_int chosen = UINT_MAX, first_prompt, y;
|
|
|
|
|
u_int chosen = UINT_MAX, first_prompt;
|
|
|
|
|
u_int target = request->target;
|
|
|
|
|
int changed = 0, enabled = 0, found, initial;
|
|
|
|
|
int changed = 0, enabled = 0;
|
|
|
|
|
int found, initial;
|
|
|
|
|
int wanted;
|
|
|
|
|
|
|
|
|
|
if (data->source == NULL)
|
|
|
|
|
@@ -4364,44 +4308,30 @@ window_copy_set_fold(struct window_mode_entry *wme,
|
|
|
|
|
window_copy_cursor_source(wme, &source_x, &source_y);
|
|
|
|
|
if (target == UINT_MAX)
|
|
|
|
|
target = source_y;
|
|
|
|
|
first_prompt = screen_hsize(data->source) + screen_size_y(data->source);
|
|
|
|
|
for (y = 0; y < first_prompt; y++) {
|
|
|
|
|
if (grid_get_line(data->source->grid, y)->flags &
|
|
|
|
|
GRID_LINE_START_PROMPT) {
|
|
|
|
|
first_prompt = y;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
initial = first_prompt != 0 &&
|
|
|
|
|
first_prompt != screen_hsize(data->source) +
|
|
|
|
|
screen_size_y(data->source) && target < first_prompt;
|
|
|
|
|
first_prompt = window_copy_first_prompt(data->source->grid);
|
|
|
|
|
initial = (first_prompt != 0 && first_prompt != UINT_MAX &&
|
|
|
|
|
target < first_prompt);
|
|
|
|
|
if (!data->fold_view) {
|
|
|
|
|
data->fold_view = 1;
|
|
|
|
|
window_copy_rebuild_backing(wme);
|
|
|
|
|
enabled = 1;
|
|
|
|
|
}
|
|
|
|
|
found = window_copy_find_fold(wme, target, &prompt, &chosen);
|
|
|
|
|
wanted = (request->action == WINDOW_COPY_FOLD_COLLAPSE);
|
|
|
|
|
if (request->all) {
|
|
|
|
|
wanted = (request->action == WINDOW_COPY_FOLD_COLLAPSE);
|
|
|
|
|
if (request->action == WINDOW_COPY_FOLD_TOGGLE)
|
|
|
|
|
wanted = !window_copy_any_fold_collapsed(data);
|
|
|
|
|
changed = window_copy_set_all_folds(data, wanted);
|
|
|
|
|
} else if (initial) {
|
|
|
|
|
wanted = (request->action == WINDOW_COPY_FOLD_COLLAPSE);
|
|
|
|
|
if (request->action == WINDOW_COPY_FOLD_TOGGLE)
|
|
|
|
|
wanted = !(data->source_flags[0] &
|
|
|
|
|
WINDOW_COPY_FOLD_COLLAPSED);
|
|
|
|
|
if (window_copy_set_source_folded(data, 0, wanted)) {
|
|
|
|
|
changed = 1;
|
|
|
|
|
}
|
|
|
|
|
changed = window_copy_set_source_folded(data, 0, wanted);
|
|
|
|
|
} else if (found && chosen != UINT_MAX) {
|
|
|
|
|
wanted = (request->action == WINDOW_COPY_FOLD_COLLAPSE);
|
|
|
|
|
if (request->action == WINDOW_COPY_FOLD_TOGGLE)
|
|
|
|
|
wanted = !(data->source_flags[chosen] &
|
|
|
|
|
WINDOW_COPY_FOLD_COLLAPSED);
|
|
|
|
|
if (window_copy_set_source_folded(data, chosen, wanted)) {
|
|
|
|
|
changed = 1;
|
|
|
|
|
}
|
|
|
|
|
changed = window_copy_set_source_folded(data, chosen, wanted);
|
|
|
|
|
}
|
|
|
|
|
if (!changed) {
|
|
|
|
|
if (enabled) {
|
|
|
|
|
@@ -4431,7 +4361,7 @@ window_copy_set_fold(struct window_mode_entry *wme,
|
|
|
|
|
static enum window_copy_cmd_action
|
|
|
|
|
window_copy_cmd_collapse_output(struct window_copy_cmd_state *cs)
|
|
|
|
|
{
|
|
|
|
|
struct window_copy_fold_request request = {
|
|
|
|
|
struct window_copy_fold_request request = {
|
|
|
|
|
.action = WINDOW_COPY_FOLD_COLLAPSE,
|
|
|
|
|
.all = args_has(cs->wargs, 'a'),
|
|
|
|
|
.target = UINT_MAX
|
|
|
|
|
@@ -4445,7 +4375,7 @@ window_copy_cmd_collapse_output(struct window_copy_cmd_state *cs)
|
|
|
|
|
static enum window_copy_cmd_action
|
|
|
|
|
window_copy_cmd_expand_output(struct window_copy_cmd_state *cs)
|
|
|
|
|
{
|
|
|
|
|
struct window_copy_fold_request request = {
|
|
|
|
|
struct window_copy_fold_request request = {
|
|
|
|
|
.action = WINDOW_COPY_FOLD_EXPAND,
|
|
|
|
|
.all = args_has(cs->wargs, 'a'),
|
|
|
|
|
.target = UINT_MAX
|
|
|
|
|
@@ -4461,7 +4391,7 @@ window_copy_cmd_toggle_output(struct window_copy_cmd_state *cs)
|
|
|
|
|
{
|
|
|
|
|
struct window_copy_mode_data *data = cs->wme->data;
|
|
|
|
|
struct window_copy_line *line;
|
|
|
|
|
struct window_copy_fold_request request = {
|
|
|
|
|
struct window_copy_fold_request request = {
|
|
|
|
|
.action = WINDOW_COPY_FOLD_TOGGLE,
|
|
|
|
|
.all = args_has(cs->wargs, 'a'),
|
|
|
|
|
.target = UINT_MAX
|
|
|
|
|
@@ -4469,26 +4399,31 @@ window_copy_cmd_toggle_output(struct window_copy_cmd_state *cs)
|
|
|
|
|
u_int current, current_prompt, target;
|
|
|
|
|
u_int target_prompt, chosen, x, y;
|
|
|
|
|
int current_found;
|
|
|
|
|
int initial, target_found;
|
|
|
|
|
int initial;
|
|
|
|
|
|
|
|
|
|
if (args_has(cs->wargs, 'm')) {
|
|
|
|
|
if (cs->m == NULL || cmd_mouse_at(cs->wme->wp, cs->m, &x, &y,
|
|
|
|
|
0) != 0 || x >= window_copy_left_margin(cs->wme))
|
|
|
|
|
if (cs->m == NULL)
|
|
|
|
|
return (WINDOW_COPY_CMD_NOTHING);
|
|
|
|
|
if (cmd_mouse_at(cs->wme->wp, cs->m, &x, &y, 0) != 0)
|
|
|
|
|
return (WINDOW_COPY_CMD_NOTHING);
|
|
|
|
|
if (x >= window_copy_left_margin(cs->wme))
|
|
|
|
|
return (WINDOW_COPY_CMD_NOTHING);
|
|
|
|
|
target = screen_hsize(data->backing) + y - data->oy;
|
|
|
|
|
line = window_copy_get_line_info(data, target);
|
|
|
|
|
if (line == NULL || line->source_line == UINT_MAX)
|
|
|
|
|
return (WINDOW_COPY_CMD_NOTHING);
|
|
|
|
|
initial = line->flags & WINDOW_COPY_LINE_INITIAL;
|
|
|
|
|
window_copy_cursor_source(cs->wme, &x, ¤t);
|
|
|
|
|
current_found = window_copy_find_fold(cs->wme, current,
|
|
|
|
|
¤t_prompt, &chosen);
|
|
|
|
|
target_found = initial || window_copy_find_fold(cs->wme,
|
|
|
|
|
line->source_line, &target_prompt, &chosen);
|
|
|
|
|
if (!target_found)
|
|
|
|
|
return (WINDOW_COPY_CMD_NOTHING);
|
|
|
|
|
request.command_end = initial || !current_found ||
|
|
|
|
|
current_prompt != target_prompt;
|
|
|
|
|
request.command_end = 1;
|
|
|
|
|
if (!initial) {
|
|
|
|
|
if (!window_copy_find_fold(cs->wme, line->source_line,
|
|
|
|
|
&target_prompt, &chosen))
|
|
|
|
|
return (WINDOW_COPY_CMD_NOTHING);
|
|
|
|
|
window_copy_cursor_source(cs->wme, &x, ¤t);
|
|
|
|
|
current_found = window_copy_find_fold(cs->wme, current,
|
|
|
|
|
¤t_prompt, &chosen);
|
|
|
|
|
request.command_end = !current_found ||
|
|
|
|
|
current_prompt != target_prompt;
|
|
|
|
|
}
|
|
|
|
|
request.target = line->source_line;
|
|
|
|
|
}
|
|
|
|
|
if (window_copy_set_fold(cs->wme, &request))
|
|
|
|
|
@@ -5178,7 +5113,8 @@ window_copy_command(struct window_mode_entry *wme, struct client *c,
|
|
|
|
|
enum window_copy_cmd_action action;
|
|
|
|
|
enum window_copy_cmd_clear clear = WINDOW_COPY_CMD_CLEAR_NEVER;
|
|
|
|
|
const char *command;
|
|
|
|
|
u_int i, count = args_count(args), mouse_x, mouse_y;
|
|
|
|
|
u_int i, count = args_count(args);
|
|
|
|
|
u_int mouse_x, mouse_y;
|
|
|
|
|
int keys, flags, mouse_control = 0;
|
|
|
|
|
char *error = NULL;
|
|
|
|
|
|
|
|
|
|
@@ -6606,12 +6542,12 @@ static u_int
|
|
|
|
|
window_copy_left_margin(struct window_mode_entry *wme)
|
|
|
|
|
{
|
|
|
|
|
struct window_copy_mode_data *data = wme->data;
|
|
|
|
|
u_int width = 0;
|
|
|
|
|
u_int width;
|
|
|
|
|
|
|
|
|
|
width = window_copy_line_number_width(wme);
|
|
|
|
|
if (data->fold_view)
|
|
|
|
|
width = data->output_status_width + 2;
|
|
|
|
|
|
|
|
|
|
return (window_copy_line_number_width(wme) + width);
|
|
|
|
|
width += data->output_status_width + 2;
|
|
|
|
|
return (width);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static u_int
|
|
|
|
|
@@ -6702,6 +6638,61 @@ window_copy_get_current_offset(struct window_pane *wp, u_int *offset,
|
|
|
|
|
return (1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
window_copy_write_gutter(struct window_mode_entry *wme,
|
|
|
|
|
struct screen_write_ctx *ctx, u_int py, u_int line_width,
|
|
|
|
|
const struct grid_cell *gc)
|
|
|
|
|
{
|
|
|
|
|
struct window_copy_mode_data *data = wme->data;
|
|
|
|
|
struct window_copy_line *line, *next;
|
|
|
|
|
struct grid_cell control_gc;
|
|
|
|
|
u_int backing_y, output_line = UINT_MAX, i;
|
|
|
|
|
u_int width = data->output_status_width + 2;
|
|
|
|
|
char control = ' ', *status;
|
|
|
|
|
|
|
|
|
|
backing_y = screen_hsize(data->backing) - data->oy + py;
|
|
|
|
|
line = window_copy_get_line_info(data, backing_y);
|
|
|
|
|
if (line != NULL && line->flags & WINDOW_COPY_LINE_CONTROL) {
|
|
|
|
|
if (line->flags & WINDOW_COPY_LINE_INITIAL)
|
|
|
|
|
output_line = 0;
|
|
|
|
|
else if (line->flags & WINDOW_COPY_LINE_EXPANDABLE &&
|
|
|
|
|
line->output_line < data->source_line_count)
|
|
|
|
|
output_line = line->output_line;
|
|
|
|
|
if (output_line != UINT_MAX) {
|
|
|
|
|
if (data->source_flags[output_line] &
|
|
|
|
|
WINDOW_COPY_FOLD_COLLAPSED)
|
|
|
|
|
control = '+';
|
|
|
|
|
else
|
|
|
|
|
control = '-';
|
|
|
|
|
}
|
|
|
|
|
} else if (line != NULL && line->flags & WINDOW_COPY_LINE_MEMBER) {
|
|
|
|
|
next = window_copy_get_line_info(data, backing_y + 1);
|
|
|
|
|
if (next == NULL || ~next->flags & WINDOW_COPY_LINE_MEMBER ||
|
|
|
|
|
next->output_line != line->output_line)
|
|
|
|
|
control = 'm'; /* ACS L character */
|
|
|
|
|
else
|
|
|
|
|
control = 'x'; /* ACS | character */
|
|
|
|
|
}
|
|
|
|
|
screen_write_cursormove(ctx, line_width, py, 0);
|
|
|
|
|
for (i = 0; i < width; i++)
|
|
|
|
|
screen_write_putc(ctx, gc, ' ');
|
|
|
|
|
if (control != ' ') {
|
|
|
|
|
screen_write_cursormove(ctx,
|
|
|
|
|
line_width + data->output_status_width, py, 0);
|
|
|
|
|
memcpy(&control_gc, gc, sizeof control_gc);
|
|
|
|
|
if (control == 'x' || control == 'm')
|
|
|
|
|
control_gc.attr |= GRID_ATTR_CHARSET;
|
|
|
|
|
screen_write_putc(ctx, &control_gc, control);
|
|
|
|
|
}
|
|
|
|
|
if (line != NULL && line->flags & WINDOW_COPY_LINE_CONTROL) {
|
|
|
|
|
status = window_copy_expand_exit_status(wme, line);
|
|
|
|
|
screen_write_cursormove(ctx, line_width, py, 0);
|
|
|
|
|
format_draw(ctx, gc, data->output_status_width, status, NULL,
|
|
|
|
|
0);
|
|
|
|
|
free(status);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
window_copy_write_line(struct window_mode_entry *wme,
|
|
|
|
|
struct screen_write_ctx *ctx, u_int py)
|
|
|
|
|
@@ -6712,22 +6703,18 @@ window_copy_write_line(struct window_mode_entry *wme,
|
|
|
|
|
struct options *oo = wp->window->options;
|
|
|
|
|
struct grid_cell gc, mgc, cgc, mkgc, clgc, ln_gc;
|
|
|
|
|
struct grid_cell cur_ln_gc;
|
|
|
|
|
struct grid_cell control_gc;
|
|
|
|
|
struct window_copy_line *line, *next;
|
|
|
|
|
const struct grid_cell *line_gc;
|
|
|
|
|
u_int sx = screen_size_x(s);
|
|
|
|
|
u_int hsize = screen_hsize(data->backing);
|
|
|
|
|
u_int width, line_width, gutter_width, backing_y;
|
|
|
|
|
u_int width, line_width, backing_y;
|
|
|
|
|
u_int absolute, line_number, content_sx;
|
|
|
|
|
u_int i;
|
|
|
|
|
const char *value;
|
|
|
|
|
char *expanded, *status;
|
|
|
|
|
char *expanded;
|
|
|
|
|
struct format_tree *ft;
|
|
|
|
|
char control;
|
|
|
|
|
int current, mode;
|
|
|
|
|
|
|
|
|
|
line_width = window_copy_line_number_width(wme);
|
|
|
|
|
gutter_width = data->fold_view ? data->output_status_width + 2 : 0;
|
|
|
|
|
width = line_width + gutter_width;
|
|
|
|
|
width = window_copy_left_margin(wme);
|
|
|
|
|
if (width >= sx)
|
|
|
|
|
content_sx = 1;
|
|
|
|
|
else if (width != 0)
|
|
|
|
|
@@ -6755,6 +6742,7 @@ window_copy_write_line(struct window_mode_entry *wme,
|
|
|
|
|
"copy-mode-current-line-number-style", ft);
|
|
|
|
|
cur_ln_gc.flags |= GRID_FLAG_NOPALETTE;
|
|
|
|
|
current = (py == data->cy);
|
|
|
|
|
line_gc = current ? &cur_ln_gc : &ln_gc;
|
|
|
|
|
backing_y = hsize - data->oy + py;
|
|
|
|
|
absolute = backing_y + 1;
|
|
|
|
|
if (data->lines != NULL && backing_y < data->line_count &&
|
|
|
|
|
@@ -6780,62 +6768,12 @@ window_copy_write_line(struct window_mode_entry *wme,
|
|
|
|
|
line_number = data->cy - py;
|
|
|
|
|
if (line_width != 0) {
|
|
|
|
|
screen_write_cursormove(ctx, 0, py, 0);
|
|
|
|
|
screen_write_nputs(ctx, line_width,
|
|
|
|
|
current ? &cur_ln_gc : &ln_gc, "%*u ",
|
|
|
|
|
screen_write_nputs(ctx, line_width, line_gc, "%*u ",
|
|
|
|
|
(int)line_width - 1, line_number);
|
|
|
|
|
}
|
|
|
|
|
if (gutter_width != 0) {
|
|
|
|
|
line = NULL;
|
|
|
|
|
control = ' ';
|
|
|
|
|
if (data->lines != NULL && backing_y < data->line_count)
|
|
|
|
|
line = &data->lines[backing_y];
|
|
|
|
|
if (line != NULL &&
|
|
|
|
|
line->flags & WINDOW_COPY_LINE_CONTROL) {
|
|
|
|
|
if (line->flags &
|
|
|
|
|
WINDOW_COPY_LINE_INITIAL) {
|
|
|
|
|
control = data->source_flags[0] &
|
|
|
|
|
WINDOW_COPY_FOLD_COLLAPSED ? '+' : '-';
|
|
|
|
|
} else if (line->flags & WINDOW_COPY_LINE_EXPANDABLE &&
|
|
|
|
|
line->output_line < data->source_line_count) {
|
|
|
|
|
if (data->source_flags[line->output_line] &
|
|
|
|
|
WINDOW_COPY_FOLD_COLLAPSED)
|
|
|
|
|
control = '+';
|
|
|
|
|
else
|
|
|
|
|
control = '-';
|
|
|
|
|
}
|
|
|
|
|
} else if (line != NULL &&
|
|
|
|
|
line->flags & WINDOW_COPY_LINE_MEMBER) {
|
|
|
|
|
next = NULL;
|
|
|
|
|
if (backing_y + 1 < data->line_count)
|
|
|
|
|
next = &data->lines[backing_y + 1];
|
|
|
|
|
if (next == NULL ||
|
|
|
|
|
~(next->flags) & WINDOW_COPY_LINE_MEMBER ||
|
|
|
|
|
next->output_line != line->output_line)
|
|
|
|
|
control = 'm'; /* ACS L character */
|
|
|
|
|
else
|
|
|
|
|
control = 'x'; /* ACS | character */
|
|
|
|
|
}
|
|
|
|
|
screen_write_cursormove(ctx, line_width, py, 0);
|
|
|
|
|
for (i = 0; i < gutter_width; i++)
|
|
|
|
|
screen_write_putc(ctx, current ? &cur_ln_gc : &ln_gc, ' ');
|
|
|
|
|
if (control != ' ') {
|
|
|
|
|
screen_write_cursormove(ctx,
|
|
|
|
|
line_width + data->output_status_width, py, 0);
|
|
|
|
|
memcpy(&control_gc, current ? &cur_ln_gc : &ln_gc,
|
|
|
|
|
sizeof control_gc);
|
|
|
|
|
if (control == 'x' || control == 'm')
|
|
|
|
|
control_gc.attr |= GRID_ATTR_CHARSET;
|
|
|
|
|
screen_write_putc(ctx, &control_gc, control);
|
|
|
|
|
}
|
|
|
|
|
if (line != NULL &&
|
|
|
|
|
line->flags & WINDOW_COPY_LINE_CONTROL) {
|
|
|
|
|
status = window_copy_expand_exit_status(wme, line);
|
|
|
|
|
screen_write_cursormove(ctx, line_width, py, 0);
|
|
|
|
|
format_draw(ctx, current ? &cur_ln_gc : &ln_gc,
|
|
|
|
|
data->output_status_width, status, NULL, 0);
|
|
|
|
|
free(status);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (data->fold_view)
|
|
|
|
|
window_copy_write_gutter(wme, ctx, py, line_width,
|
|
|
|
|
line_gc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
window_copy_write_one(wme, ctx, width, py, hsize - data->oy + py,
|
|
|
|
|
@@ -6847,7 +6785,8 @@ window_copy_write_line(struct window_mode_entry *wme,
|
|
|
|
|
expanded = format_expand(ft, value);
|
|
|
|
|
if (*expanded != '\0') {
|
|
|
|
|
screen_write_cursormove(ctx, width, 0, 0);
|
|
|
|
|
format_draw(ctx, &gc, content_sx, expanded, NULL, 0);
|
|
|
|
|
format_draw(ctx, &gc, content_sx, expanded,
|
|
|
|
|
NULL, 0);
|
|
|
|
|
}
|
|
|
|
|
free(expanded);
|
|
|
|
|
}
|
|
|
|
|
@@ -7456,7 +7395,8 @@ window_copy_find_previous_output_range(struct screen *s, u_int cursor_x,
|
|
|
|
|
struct osc133_data *od;
|
|
|
|
|
u_int start_x, start_y, end_x, end_y;
|
|
|
|
|
u_int y, total;
|
|
|
|
|
int found = 0, found_empty = 0, have_prompt = 0;
|
|
|
|
|
int found = 0, found_empty = 0;
|
|
|
|
|
int have_prompt = 0;
|
|
|
|
|
int pending = 0, started_here;
|
|
|
|
|
int has_start, has_end, end_first;
|
|
|
|
|
|
|
|
|
|
@@ -7491,12 +7431,7 @@ window_copy_find_previous_output_range(struct screen *s, u_int cursor_x,
|
|
|
|
|
end_x = od->out_end_col;
|
|
|
|
|
end_y = y;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Prefer a previously found non-empty output over a
|
|
|
|
|
* later one that turns out to be empty (for example a
|
|
|
|
|
* command with no output immediately followed by the
|
|
|
|
|
* cursor's prompt).
|
|
|
|
|
*/
|
|
|
|
|
/* Prefer earlier output to a later empty command. */
|
|
|
|
|
if (!found || found_empty ||
|
|
|
|
|
start_x != end_x || start_y != end_y) {
|
|
|
|
|
*sx = start_x;
|
|
|
|
|
@@ -7538,13 +7473,12 @@ window_copy_get_output(struct window_mode_entry *wme, size_t *len, int all)
|
|
|
|
|
{
|
|
|
|
|
struct window_copy_mode_data *data = wme->data;
|
|
|
|
|
struct grid *gd;
|
|
|
|
|
void *buf;
|
|
|
|
|
u_int sx, sy, ex, ey, total;
|
|
|
|
|
|
|
|
|
|
if (data->source == NULL) {
|
|
|
|
|
*len = 0;
|
|
|
|
|
return (NULL);
|
|
|
|
|
}
|
|
|
|
|
gd = data->source->grid;
|
|
|
|
|
gd = data->backing->grid;
|
|
|
|
|
if (data->source != NULL)
|
|
|
|
|
gd = data->source->grid;
|
|
|
|
|
total = gd->hsize + gd->sy;
|
|
|
|
|
if (all) {
|
|
|
|
|
sx = sy = 0;
|
|
|
|
|
@@ -7554,7 +7488,8 @@ window_copy_get_output(struct window_mode_entry *wme, size_t *len, int all)
|
|
|
|
|
*len = 0;
|
|
|
|
|
return (NULL);
|
|
|
|
|
}
|
|
|
|
|
return (window_copy_get_grid_range(gd, sx, sy, ex, ey, len));
|
|
|
|
|
buf = window_copy_get_grid_range(gd, sx, sy, ex, ey, len);
|
|
|
|
|
return (buf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *
|
|
|
|
|
|