From f52b6cf19f4f5c0f0aa3657a3742b5803decd366 Mon Sep 17 00:00:00 2001 From: Benno Schulenberg Date: Mon, 30 Mar 2020 13:51:15 +0200 Subject: [PATCH] copying: change the implementation, away from cutting plus copying back First cutting the text to be copied (before copying it back into the buffer) had unwanted side effects: it moved the cursor, and changed the linestructs of the current line and the line where the mark was. [This takes thirty more lines, but the idea is to later get rid of the partitioning routines entirely.] --- src/cut.c | 174 ++++++++++++++++++++++++++++++---------------------- src/files.c | 2 +- src/nano.h | 3 +- src/proto.h | 1 + 4 files changed, 104 insertions(+), 76 deletions(-) diff --git a/src/cut.c b/src/cut.c index 2cc07467..8a9221f2 100644 --- a/src/cut.c +++ b/src/cut.c @@ -449,49 +449,23 @@ void cut_to_eof(void) } #endif /* !NANO_TINY */ -/* Move text from the current buffer into the cutbuffer. If - * copying is TRUE, copy the text back into the buffer afterward. +/* Move text from the current buffer into the cutbuffer. * If until_eof is TRUE, move all text from the current cursor * position to the end of the file into the cutbuffer. If append * is TRUE (when zapping), always append the cut to the cutbuffer. */ void do_snip(bool copying, bool marked, bool until_eof, bool append) { -#ifndef NANO_TINY - linestruct *was_bottom = NULL; - /* The current end of the cutbuffer, before we add text to it. */ - size_t botlen = 0; - /* The length of the string at the current end of the cutbuffer, - * before we add text to it. */ - bool using_magicline = !ISSET(NO_NEWLINES); - /* Whether an automatic newline should be added at end-of-buffer. */ - bool right_side_up = (openfile->mark == NULL || mark_is_before_cursor()); - /* There *is* no region, *or* it is marked forward. */ -#endif - static bool precedent = FALSE; - /* Whether the previous operation was a copying operation. */ - /* If cuts were not continuous, or when cutting a region, clear the slate. */ - if ((!keep_cutbuffer || marked || until_eof || copying != precedent) && - !append) { + if ((!keep_cutbuffer || marked || until_eof || + openfile->last_action == COPY) && !append) { free_lines(cutbuffer); cutbuffer = NULL; } /* After a line operation, future ones should add to the cutbuffer. */ keep_cutbuffer = !marked && !until_eof; - precedent = copying; #ifndef NANO_TINY - if (copying) { - /* If the cutbuffer isn't empty, remember where it currently ends. */ - if (cutbuffer != NULL) { - was_bottom = cutbottom; - botlen = strlen(cutbottom->data); - } - /* Don't add a magic line when moving text to the cutbuffer. */ - SET(NO_NEWLINES); - } - /* Now move the relevant piece of text into the cutbuffer. */ if (until_eof) cut_to_eof(); @@ -504,30 +478,7 @@ void do_snip(bool copying, bool marked, bool until_eof, bool append) #endif cut_line(); -#ifndef NANO_TINY - if (copying) { - /* Copy the text that was put into the cutbuffer back into the current - * file buffer, so that in the end nothing has been deleted. */ - if (cutbuffer != NULL) { - if (was_bottom != NULL) { - was_bottom->data += botlen; - copy_from_buffer(was_bottom); - was_bottom->data -= botlen; - } else - copy_from_buffer(cutbuffer); - - /* If the copied region was marked forward, put the new desired - * x position at its end; otherwise, leave it at its beginning. */ - if (right_side_up) - openfile->placewewant = xplustabs(); - } - /* Restore the magic-line behavior now that we're done fiddling. */ - if (using_magicline) - UNSET(NO_NEWLINES); - } else -#endif - set_modified(); - + set_modified(); refresh_needed = TRUE; } @@ -556,31 +507,106 @@ void cut_text(void) } #ifndef NANO_TINY -/* Move text from the current buffer into the cutbuffer, and copy it - * back into the buffer afterward. If the mark is set or the cursor - * was moved, blow away previous contents of the cutbuffer. */ -void copy_text(void) +/* Make a copy of the marked region, putting it in the cutbuffer. */ +void copy_marked_region(void) { - bool mark_is_set = (openfile->mark != NULL); + linestruct *topline, *botline, *afterline; + char *was_datastart, saved_byte; + size_t top_x, bot_x; - /* Remember the current viewport and cursor position. */ - ssize_t is_edittop_lineno = openfile->edittop->lineno; - size_t is_firstcolumn = openfile->firstcolumn; - ssize_t is_current_lineno = openfile->current->lineno; - size_t is_current_x = openfile->current_x; - - do_snip(TRUE, mark_is_set, FALSE, FALSE); - - /* If the mark was set, restore the viewport and cursor position. */ - if (mark_is_set) { - openfile->edittop = line_from_number(is_edittop_lineno); - openfile->firstcolumn = is_firstcolumn; - openfile->current = line_from_number(is_current_lineno); - openfile->current_x = is_current_x; - } else - focusing = FALSE; + get_region(&topline, &top_x, &botline, &bot_x); openfile->last_action = OTHER; + keep_cutbuffer = FALSE; + openfile->mark = NULL; + refresh_needed = TRUE; + + if (topline == botline && top_x == bot_x) + return; + + /* Make the area that was marked look like a separate buffer. */ + afterline = botline->next; + botline->next = NULL; + saved_byte = botline->data[bot_x]; + botline->data[bot_x] = '\0'; + was_datastart = topline->data; + topline->data += top_x; + + cutbuffer = copy_buffer(topline); + + /* Restore the proper state of the buffer. */ + topline->data = was_datastart; + botline->data[bot_x] = saved_byte; + botline->next = afterline; +} + +/* Copy text from the current buffer into the cutbuffer. */ +void copy_text(void) +{ + bool at_eol = (openfile->current->data[openfile->current_x] == '\0'); + linestruct *addition; + + if (openfile->mark || openfile->last_action != COPY || !keep_cutbuffer) { + free_lines(cutbuffer); + cutbuffer = NULL; + } + + if (openfile->mark) { + copy_marked_region(); + return; + } + + addition = make_new_node(NULL); + + /* Create OR add to the cutbuffer, depending on the mode, the position + * of the cursor, and whether or not the cutbuffer is currently empty. */ + if (ISSET(CUT_FROM_CURSOR)) { + addition->data = copy_of(openfile->current->data + openfile->current_x); + + if (cutbuffer == NULL && !at_eol) { + cutbuffer = addition; + cutbottom = addition; + } else if (cutbuffer == NULL) { + cutbuffer = addition; + cutbottom = make_new_node(cutbuffer); + cutbottom->data = copy_of(""); + cutbuffer->next = cutbottom; + } else if (at_eol) { + addition->prev = cutbottom; + cutbottom->next = addition; + cutbottom = addition; + } else { + addition->prev = cutbottom->prev; + addition->prev->next = addition; + delete_node(cutbottom); + cutbottom = addition; + } + } else { + addition->data = copy_of(openfile->current->data); + + if (cutbuffer == NULL) { + cutbuffer = addition; + cutbottom = make_new_node(cutbuffer); + cutbottom->data = copy_of(""); + cutbuffer->next = cutbottom; + } else { + addition->prev = cutbottom->prev; + addition->prev->next = addition; + addition->next = cutbottom; + cutbottom->prev = addition; + } + } + + if ((!ISSET(CUT_FROM_CURSOR) || at_eol) && openfile->current->next) { + openfile->current = openfile->current->next; + openfile->current_x = 0; + } else + openfile->current_x = strlen(openfile->current->data); + + openfile->placewewant = xplustabs(); + + openfile->last_action = COPY; + keep_cutbuffer = TRUE; } /* Cut from the current cursor position to the end of the file. */ diff --git a/src/files.c b/src/files.c index 97315ac7..535519c0 100644 --- a/src/files.c +++ b/src/files.c @@ -1044,7 +1044,7 @@ bool execute_command(const char *command) if (ISSET(MULTIBUFFER)) { openfile = openfile->prev; if (openfile->mark) - do_snip(TRUE, TRUE, FALSE, FALSE); + copy_marked_region(); else whole_buffer = TRUE; } else diff --git a/src/nano.h b/src/nano.h index 9c53987a..a4a15d84 100644 --- a/src/nano.h +++ b/src/nano.h @@ -172,7 +172,8 @@ typedef enum { #ifdef ENABLE_COMMENT COMMENT, UNCOMMENT, PREFLIGHT, #endif - ZAP, CUT, CUT_TO_EOF, PASTE, INSERT, COUPLE_BEGIN, COUPLE_END, OTHER + ZAP, CUT, CUT_TO_EOF, COPY, PASTE, INSERT, + COUPLE_BEGIN, COUPLE_END, OTHER } undo_type; /* Structure types. */ diff --git a/src/proto.h b/src/proto.h index 154c4209..e90bdef4 100644 --- a/src/proto.h +++ b/src/proto.h @@ -266,6 +266,7 @@ void cut_marked_region(void); void do_snip(bool copying, bool marked, bool until_eof, bool append); void cut_text(void); #ifndef NANO_TINY +void copy_marked_region(void); void copy_text(void); void cut_till_eof(void); void zap_text(void);