From 833d3dc0faa883dbd4762dd313d7098e4293d0d3 Mon Sep 17 00:00:00 2001 From: Michael Grant Date: Wed, 7 Oct 2026 15:15:00 +0200 Subject: [PATCH] Add comments explaining the OSC 133 output range search. --- grid-reader.c | 20 ++++++++++++++++++-- grid.c | 1 + window-copy.c | 4 ++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/grid-reader.c b/grid-reader.c index 9c9b411b2..edde03f95 100644 --- a/grid-reader.c +++ b/grid-reader.c @@ -474,6 +474,7 @@ grid_reader_previous_output_range(struct grid_reader *gr, u_int *sx, for (y = 0; y < total && y <= cursor_y; y++) { gl = grid_get_line(gd, y); od = &gl->osc133_data; + /* On the cursor's line, ignore markers after the cursor. */ has_start = has_end = end_first = 0; if (gl->flags & GRID_LINE_START_OUTPUT) { if (y != cursor_y || od->out_start_col <= cursor_x) @@ -486,6 +487,7 @@ grid_reader_previous_output_range(struct grid_reader *gr, u_int *sx, /* An end before the start ends the previous output. */ if (has_start && has_end && od->out_end_col < od->out_start_col) end_first = 1; + /* A C marker starts an output that is pending until its D. */ if (has_start && !end_first) { start_x = od->out_start_col; start_y = y; @@ -503,6 +505,7 @@ grid_reader_previous_output_range(struct grid_reader *gr, u_int *sx, pending = 1; } } + /* A D marker completes the pending output. */ if (pending && has_end) { *sx = start_x; *sy = start_y; @@ -517,7 +520,7 @@ grid_reader_previous_output_range(struct grid_reader *gr, u_int *sx, pending = 1; } if (gl->flags & GRID_LINE_START_PROMPT) { - /* Output may start after the prompt. */ + /* A prompt drops an unfinished output. */ if (!has_start || od->out_start_col < od->prompt_col) pending = 0; have_prompt = 1; @@ -526,7 +529,11 @@ grid_reader_previous_output_range(struct grid_reader *gr, u_int *sx, return (found); } -/* Find the output range for the command at the cursor. */ +/* + * Find the output range for the command at the cursor, from its C marker to + * its D marker. If the prompt has no output yet, use the previous output. + * Returns 0 if there is no usable range. + */ int grid_reader_output_range(struct grid_reader *gr, u_int *sx, u_int *sy, u_int *ex, u_int *ey) @@ -543,6 +550,7 @@ grid_reader_output_range(struct grid_reader *gr, u_int *sx, u_int *sy, log_debug("%s: cursor at %u,%u", __func__, cursor_x, cursor_y); + /* Find the last prompt at or before the cursor. */ total = gd->hsize + gd->sy; for (y = 0; y < total; y++) { gl = grid_get_line(gd, y); @@ -556,6 +564,7 @@ grid_reader_output_range(struct grid_reader *gr, u_int *sx, u_int *sy, prompt_y = y; prompt_x = od->prompt_col; } + /* With no prompt, its A marker may have left history, so start at 0. */ if (prompt_y == UINT_MAX) { log_debug("%s: no osc133 prompt before cursor", __func__); y = 0; @@ -565,6 +574,7 @@ grid_reader_output_range(struct grid_reader *gr, u_int *sx, u_int *sy, y = prompt_y; } + /* Walk down from the prompt to its C and D, up to the next prompt. */ for (; y < total; y++) { gl = grid_get_line(gd, y); od = &gl->osc133_data; @@ -608,11 +618,17 @@ grid_reader_output_range(struct grid_reader *gr, u_int *sx, u_int *sy, if (next_prompt) break; } + /* The cursor is on a prompt with no output yet. */ if (!found_start) { log_debug("%s: no output after prompt", __func__); found = grid_reader_previous_output_range(gr, sx, sy, ex, ey); return (found); } + /* + * Without a D marker the command is still running, so its output runs + * to the last used line. If the next prompt came first, it has no + * usable end. + */ if (!found_end) { if (y != total) { log_debug("%s: output interrupted by next prompt", diff --git a/grid.c b/grid.c index ec6166dd7..76ffffcd8 100644 --- a/grid.c +++ b/grid.c @@ -1547,6 +1547,7 @@ grid_reflow_split(struct grid *target, struct grid *gd, u_int sx, u_int yy, /* Insert new lines. */ line = target->sy + 1; first = grid_reflow_add(target, lines); + /* The first line keeps only the markers within its first at cells. */ memcpy(first, gl, sizeof *first); first->cellsize = first->cellused = at; first->flags &= ~GRID_LINE_OSC133_FLAGS; diff --git a/window-copy.c b/window-copy.c index 0e37f56f8..9227befbd 100644 --- a/window-copy.c +++ b/window-copy.c @@ -1614,6 +1614,8 @@ window_copy_cmd_select_output(struct window_copy_cmd_state *cs) if (!window_copy_get_output_range(wme, all, &sx, &sy, &ex, &ey)) return (WINDOW_COPY_CMD_NOTHING); + + /* An empty output selects nothing. */ buf = window_copy_get_grid_range(wme, sx, sy, ex, ey, &len); if (buf == NULL) return (WINDOW_COPY_CMD_NOTHING); @@ -1625,6 +1627,7 @@ window_copy_cmd_select_output(struct window_copy_cmd_state *cs) data->selflag = SEL_CHAR; window_copy_scroll_to(wme, sx, sy, 1); window_copy_start_selection(wme); + /* The end is inclusive in vi mode, so step back onto the last cell. */ if (data->modekeys == MODEKEY_VI) { last = window_copy_copy_line_length(wme, ey, NULL); if (ex > last) @@ -6264,6 +6267,7 @@ window_copy_get_output(struct window_mode_entry *wme, size_t *len, int all) return (buf); } +/* Get the text from sx,sy up to ex,ey, or NULL if there is none. */ static void * window_copy_get_grid_range(struct window_mode_entry *wme, u_int sx, u_int sy, u_int ex, u_int ey, size_t *len)