diff --git a/src/nano.c b/src/nano.c index 5b1a160ef7f604cb9e8d9048345b0b6f7ac9b7f4..63ef707b11b2dfbddf92f180fb5a73faae644445 100644 --- a/src/nano.c +++ b/src/nano.c @@ -1775,7 +1775,7 @@ int do_mouse(void) go_forward_chunks(row_count, &openfile->current, &leftedge); openfile->current_x = actual_x(openfile->current->data, - leftedge + mouse_col); + actual_last_column(leftedge, mouse_col)); #ifndef NANO_TINY /* Clicking where the cursor is toggles the mark, as does clicking diff --git a/src/proto.h b/src/proto.h index 4e66b8e3e2154a7d099814fcb1556df23ef1ca48..aabca6ab8efda5c6b03fc2386813d7cccb388e47 100644 --- a/src/proto.h +++ b/src/proto.h @@ -665,6 +665,7 @@ void edit_scroll(scroll_dir direction, int nrows); #ifndef NANO_TINY size_t get_softwrap_breakpoint(const char *text, size_t leftedge, bool *end_of_line); +size_t actual_last_column(size_t leftedge, size_t column); size_t get_chunk(filestruct *line, size_t column, size_t *leftedge); size_t get_chunk_row(filestruct *line, size_t column); size_t get_chunk_leftedge(filestruct *line, size_t column); diff --git a/src/winio.c b/src/winio.c index e1adccb1e8cd545c9d01f4e3eec1faaf73f2a531..c8e8cc77e52b1b30d852f7f48ff7be3230b4c2c7 100644 --- a/src/winio.c +++ b/src/winio.c @@ -3028,6 +3028,34 @@ size_t get_softwrap_breakpoint(const char *text, size_t leftedge, return (editwincols > 2) ? prev_column : column - 1; } +/* When in softwrap mode, and the given column is on or after the breakpoint of + * a softwrapped chunk, shift it back to the last column before the breakpoint. + * The given column is relative to the given leftedge in current. The returned + * column is relative to the start of the text. */ +size_t actual_last_column(size_t leftedge, size_t column) +{ +#ifndef NANO_TINY + if (ISSET(SOFTWRAP)) { + size_t end_col; + bool last_chunk; + + end_col = get_softwrap_breakpoint(openfile->current->data, leftedge, + &last_chunk) - leftedge; + + /* If we're not on the last chunk, we're one column past the end of + * the row. Shifting back one column might put us in the middle of + * a multi-column character, but actual_x() will fix that later. */ + if (!last_chunk) + end_col--; + + if (column > end_col) + column = end_col; + } +#endif + + return leftedge + column; +} + /* Get the row of the softwrapped chunk of the given line that column is on, * relative to the first row (zero-based), and return it. If leftedge isn't * NULL, return the leftmost column of the chunk in it. */