From 9a67d7958fdf751f4a7ea582575bd467eefffc4f Mon Sep 17 00:00:00 2001 From: Benno Schulenberg Date: Fri, 3 Apr 2020 11:07:36 +0200 Subject: [PATCH] undo: choose the proper x positions to place the cursor and rejoin lines Normally, when undoing an that created automatic indentation, the created whitespace should be skipped when rejoining the two lines. In other words: take the data starting from tail_x in the second line. But when the occurred at the end of leading whitespace, then that whitespace has disappeared from the original line and it should be copied back in from the second line. That is: from x is zero. This fixes https://savannah.gnu.org/bugs/?58108. Reported-by: Liu Hao Bug existed since version 4.9, commit 1961c052. --- src/text.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/text.c b/src/text.c index de5df9b5..389f8674 100644 --- a/src/text.c +++ b/src/text.c @@ -504,6 +504,7 @@ void do_undo(void) linestruct *line = NULL, *intruder; linestruct *oldcutbuffer; char *data, *undidmsg = NULL; + size_t original_x, regain_from_x; if (u == NULL) { statusbar(_("Nothing to undo")); @@ -526,12 +527,17 @@ void do_undo(void) break; case ENTER: undidmsg = _("line break"); + /* An at the end of leading whitespace while autoindenting has + * deleted the whitespace, and stored an x position of zero. In that + * case, adjust the positions to return to and to scoop data from. */ + original_x = (u->head_x == 0) ? u->tail_x : u->head_x; + regain_from_x = (u->head_x == 0) ? 0 : u->tail_x; line->data = charealloc(line->data, strlen(line->data) + - strlen(&u->strdata[u->tail_x]) + 1); - strcat(line->data, &u->strdata[u->tail_x]); + strlen(&u->strdata[regain_from_x]) + 1); + strcat(line->data, &u->strdata[regain_from_x]); unlink_node(line->next); renumber_from(line); - goto_line_posx(u->head_lineno, u->head_x); + goto_line_posx(u->head_lineno, original_x); break; case BACK: case DEL: