From bd8218e85d9305cda3abbe9a54a4288e538632e9 Mon Sep 17 00:00:00 2001 From: nicm Date: Tue, 1 Sep 2026 13:04:29 +0000 Subject: [PATCH] When changing selection-mode to line, set up the selection start and end correctly, GitHub issue 5545. --- window-copy.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/window-copy.c b/window-copy.c index 572a199fb..c5529a3ff 100644 --- a/window-copy.c +++ b/window-copy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: window-copy.c,v 1.428 2026/08/31 07:42:56 nicm Exp $ */ +/* $OpenBSD: window-copy.c,v 1.429 2026/09/01 13:04:29 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -2207,15 +2207,76 @@ window_copy_cmd_selection_mode(struct window_copy_cmd_state *cs) struct window_mode_entry *wme = cs->wme; struct options *so = cs->s->options; struct window_copy_mode_data *data = wme->data; + struct grid_reader gr; const char *s = args_string(cs->wargs, 0); + u_int sx, sy, ex, ey, fx, fy, x, y; if (s == NULL || strcasecmp(s, "char") == 0 || strcasecmp(s, "c") == 0) data->selflag = SEL_CHAR; else if (strcasecmp(s, "word") == 0 || strcasecmp(s, "w") == 0) { data->separators = options_get_string(so, "word-separators"); data->selflag = SEL_WORD; - } else if (strcasecmp(s, "line") == 0 || strcasecmp(s, "l") == 0) + } else if (strcasecmp(s, "line") == 0 || strcasecmp(s, "l") == 0) { data->selflag = SEL_LINE; + if (data->screen.sel == NULL) + return (WINDOW_COPY_CMD_MOVE); + + /* + * Line selection normally starts with select-line, which sets + * up the reset positions used when the cursor changes + * direction. Do the same when changing an existing selection + * to line mode. + */ + if (data->cursordrag == CURSORDRAG_SEL) { + fx = data->endselx; + fy = data->endsely; + } else { + fx = data->selx; + fy = data->sely; + } + + sx = data->selx; + sy = data->sely; + ex = data->endselx; + ey = data->endsely; + if (ey < sy || (ey == sy && ex < sx)) { + x = sx; sx = ex; ex = x; + y = sy; sy = ey; ey = y; + } + grid_reader_start(&gr, data->backing->grid, sx, sy); + grid_reader_cursor_start_of_line(&gr, 1); + grid_reader_get_cursor(&gr, &sx, &sy); + grid_reader_start(&gr, data->backing->grid, ex, ey); + grid_reader_cursor_end_of_line(&gr, 1, 0); + grid_reader_get_cursor(&gr, &ex, &ey); + + data->rectflag = 0; + data->selrx = data->selx = sx; + data->selry = data->sely = sy; + data->endselrx = data->endselx = ex; + data->endselry = data->endsely = ey; + + x = data->cx; + y = screen_hsize(data->backing) + data->cy - data->oy; + data->dx = fx; + data->dy = fy; + if (data->cursordrag != CURSORDRAG_NONE && + (y < fy || (y == fy && x < fx))) { + data->lineflag = LINE_SEL_RIGHT_LEFT; + data->cursordrag = CURSORDRAG_SEL; + window_copy_scroll_to(wme, sx, sy, 1); + } else { + data->lineflag = LINE_SEL_LEFT_RIGHT; + if (data->cursordrag != CURSORDRAG_NONE) { + data->cursordrag = CURSORDRAG_ENDSEL; + x = window_copy_cursor_limit(wme, ey, 0); + window_copy_scroll_to(wme, x, ey, 1); + } + } + if (data->cursordrag == CURSORDRAG_NONE) + window_copy_set_selection(wme, 0, 0); + return (WINDOW_COPY_CMD_REDRAW); + } return (WINDOW_COPY_CMD_MOVE); }