undo: choose the proper x positions to place the cursor and rejoin lines

Normally, when undoing an <Enter> 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 <Enter> 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 <lh_mouse@126.com>

Bug existed since version 4.9, commit 1961c052.
master
Benno Schulenberg 2020-04-03 11:07:36 +02:00
parent 23f73cb8b3
commit 9a67d7958f
1 changed files with 9 additions and 3 deletions

View File

@ -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 <Enter> 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: