cutting: copy anchors into the cutbuffer, so that undo can restore them
When a segment of text is extracted, copy any anchors that it has into the cutbuffer, so that they get saved in the undo item, so that an undo will put these anchors back on the lines where they were, instead of leaving an inherited anchor at the top of the segment. And when text is pasted, clear any anchors in it, so that they will not travel nor multiply. This fixes https://savannah.gnu.org/bugs/?61162. Bug existed since version 5.0, since anchors were introduced.
Этот коммит содержится в:
родитель
04f8aa83ef
Коммит
189960c467
24
src/cut.c
24
src/cut.c
@ -249,6 +249,7 @@ void extract_segment(linestruct *top, size_t top_x, linestruct *bot, size_t bot_
|
||||
bool same_line = (openfile->mark == top);
|
||||
bool post_marked = (openfile->mark && (openfile->mark->lineno > top->lineno ||
|
||||
(same_line && openfile->mark_x > top_x)));
|
||||
static bool inherited_anchor = FALSE;
|
||||
bool had_anchor = top->has_anchor;
|
||||
|
||||
if (top == bot && top_x == bot_x)
|
||||
@ -269,7 +270,9 @@ void extract_segment(linestruct *top, size_t top_x, linestruct *bot, size_t bot_
|
||||
taken = top;
|
||||
last = make_new_node(NULL);
|
||||
last->data = copy_of("");
|
||||
|
||||
#ifndef NANO_TINY
|
||||
last->has_anchor = bot->has_anchor;
|
||||
#endif
|
||||
last->prev = bot->prev;
|
||||
bot->prev->next = last;
|
||||
last->next = NULL;
|
||||
@ -309,11 +312,17 @@ void extract_segment(linestruct *top, size_t top_x, linestruct *bot, size_t bot_
|
||||
if (cutbuffer == NULL) {
|
||||
cutbuffer = taken;
|
||||
cutbottom = last;
|
||||
#ifndef NANO_TINY
|
||||
inherited_anchor = taken->has_anchor;
|
||||
#endif
|
||||
} else {
|
||||
cutbottom->data = nrealloc(cutbottom->data,
|
||||
strlen(cutbottom->data) + strlen(taken->data) + 1);
|
||||
strcat(cutbottom->data, taken->data);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
cutbottom->has_anchor = taken->has_anchor && !inherited_anchor;
|
||||
inherited_anchor |= taken->has_anchor;
|
||||
#endif
|
||||
cutbottom->next = taken->next;
|
||||
delete_node(taken);
|
||||
|
||||
@ -686,6 +695,11 @@ void copy_text(void)
|
||||
/* Copy text from the cutbuffer into the current buffer. */
|
||||
void paste_text(void)
|
||||
{
|
||||
/* Remember where the paste started. */
|
||||
#ifndef NANO_TINY
|
||||
linestruct *was_current = openfile->current;
|
||||
bool had_anchor = was_current->has_anchor;
|
||||
#endif
|
||||
ssize_t was_lineno = openfile->current->lineno;
|
||||
/* The line number where we started the paste. */
|
||||
size_t was_leftedge = 0;
|
||||
@ -708,6 +722,12 @@ void paste_text(void)
|
||||
copy_from_buffer(cutbuffer);
|
||||
|
||||
#ifndef NANO_TINY
|
||||
/* Wipe any anchors in the pasted text, so that they don't move around. */
|
||||
for (linestruct *line = was_current; line != openfile->current->next; line = line->next)
|
||||
line->has_anchor = FALSE;
|
||||
|
||||
was_current->has_anchor = had_anchor;
|
||||
|
||||
update_undo(PASTE);
|
||||
#endif
|
||||
|
||||
|
@ -220,6 +220,7 @@
|
||||
#define INCLUDED_LAST_LINE (1<<3)
|
||||
#define MARK_WAS_SET (1<<4)
|
||||
#define CURSOR_WAS_AT_HEAD (1<<5)
|
||||
#define HAD_ANCHOR_AT_START (1<<6)
|
||||
#endif /* !NANO_TINY */
|
||||
|
||||
/* Identifiers for the different menus. */
|
||||
|
@ -154,7 +154,7 @@ linestruct *copy_node(const linestruct *src)
|
||||
#endif
|
||||
dst->lineno = src->lineno;
|
||||
#ifndef NANO_TINY
|
||||
dst->has_anchor = FALSE;
|
||||
dst->has_anchor = src->has_anchor;
|
||||
#endif
|
||||
|
||||
return dst;
|
||||
|
@ -463,6 +463,10 @@ void undo_cut(undostruct *u)
|
||||
{
|
||||
goto_line_posx(u->head_lineno, (u->xflags & WAS_WHOLE_LINE) ? 0 : u->head_x);
|
||||
|
||||
/* Clear an inherited anchor but not a user-placed one. */
|
||||
if (!(u->xflags & HAD_ANCHOR_AT_START))
|
||||
openfile->current->has_anchor = FALSE;
|
||||
|
||||
if (u->cutbuffer)
|
||||
copy_from_buffer(u->cutbuffer);
|
||||
|
||||
@ -1023,6 +1027,8 @@ void add_undo(undo_type action, const char *message)
|
||||
#endif
|
||||
case CUT_TO_EOF:
|
||||
u->xflags |= (INCLUDED_LAST_LINE | CURSOR_WAS_AT_HEAD);
|
||||
if (openfile->current->has_anchor)
|
||||
u->xflags |= HAD_ANCHOR_AT_START;
|
||||
break;
|
||||
case ZAP:
|
||||
case CUT:
|
||||
@ -1044,6 +1050,9 @@ void add_undo(undo_type action, const char *message)
|
||||
u->tail_x = 0;
|
||||
} else
|
||||
u->xflags |= CURSOR_WAS_AT_HEAD;
|
||||
if ((openfile->mark && mark_is_before_cursor() && openfile->mark->has_anchor) ||
|
||||
((!openfile->mark || !mark_is_before_cursor()) && openfile->current->has_anchor))
|
||||
u->xflags |= HAD_ANCHOR_AT_START;
|
||||
break;
|
||||
case PASTE:
|
||||
u->cutbuffer = copy_buffer(cutbuffer);
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user